/*
 * $Id: trident.c,v 1.126.2.13 Broadcom SDK $
 * $Copyright: Copyright 2011 Broadcom Corporation.
 * This program is the proprietary software of Broadcom Corporation
 * and/or its licensors, and may only be used, duplicated, modified
 * or distributed pursuant to the terms and conditions of a separate,
 * written license agreement executed between you and Broadcom
 * (an "Authorized License").  Except as set forth in an Authorized
 * License, Broadcom grants no license (express or implied), right
 * to use, or waiver of any kind with respect to the Software, and
 * Broadcom expressly reserves all rights in and to the Software
 * and all intellectual property rights therein.  IF YOU HAVE
 * NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE
 * IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE
 * ALL USE OF THE SOFTWARE.  
 *  
 * Except as expressly set forth in the Authorized License,
 *  
 * 1.     This program, including its structure, sequence and organization,
 * constitutes the valuable trade secrets of Broadcom, and you shall use
 * all reasonable efforts to protect the confidentiality thereof,
 * and to use this information only in connection with your use of
 * Broadcom integrated circuit products.
 *  
 * 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS
 * PROVIDED "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES,
 * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY,
 * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE.  BROADCOM SPECIFICALLY
 * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
 * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES,
 * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
 * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING
 * OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
 * 
 * 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL
 * BROADCOM OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL,
 * INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER
 * ARISING OUT OF OR IN ANY WAY RELATING TO YOUR USE OF OR INABILITY
 * TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF
 * THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR USD 1.00,
 * WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING
 * ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.$
 *
 * File:        trident.c
 * Purpose:
 * Requires:
 */


#include <sal/core/boot.h>

#include <soc/trident.h>
#include <soc/bradley.h>
#include <soc/drv.h>
#include <soc/error.h>
#include <soc/debug.h>
#include <soc/mem.h>

#ifdef BCM_TRIDENT_SUPPORT

typedef enum {
    _SOC_PARITY_TYPE_NONE,
    _SOC_PARITY_TYPE_GENERIC,
    _SOC_PARITY_TYPE_PARITY,
    _SOC_PARITY_TYPE_ECC,
    _SOC_PARITY_TYPE_HASH,
    _SOC_PARITY_TYPE_EDATABUF,
    _SOC_PARITY_TYPE_COUNTER,
    _SOC_PARITY_TYPE_XLPORT,
    _SOC_PARITY_TYPE_MMU_THDO,
    _SOC_PARITY_TYPE_SER
} _soc_trident_parity_info_type_t;

typedef struct _soc_trident_parity_reg_s {
    soc_reg_t               reg;
    char                    *mem_str;
} _soc_trident_parity_reg_t;

typedef struct _soc_trident_parity_mmu_bit_s {
    uint32 bit_pos;
    soc_mem_t mem;
} _soc_trident_parity_mmu_bit_t;

typedef struct _soc_trident_parity_info_s {
    _soc_trident_parity_info_type_t   type;
    struct _soc_trident_parity_info_s *info;
    int                               id;
    soc_field_t                       group_reg_enable_field;
    soc_field_t                       group_reg_status_field;
    soc_mem_t                         mem;
    char                              *mem_str;
    soc_reg_t                         enable_reg;
    soc_field_t                       enable_field;
    soc_reg_t                         intr_status_reg;
    _soc_trident_parity_reg_t         *intr_status_reg_list;
    soc_reg_t                         nack_status_reg;
    _soc_trident_parity_reg_t         *nack_status_reg_list;
} _soc_trident_parity_info_t;

typedef struct _soc_trident_parity_route_block_s {
    uint32             cmic_bit;
    soc_block_t        blocktype;
    int                pipe;
    soc_reg_t          enable_reg;
    soc_reg_t          status_reg;
    _soc_trident_parity_info_t *info;
} _soc_trident_parity_route_block_t;

STATIC _soc_trident_parity_reg_t _soc_trident_egr_vlan_xlate_intr_reg[] = {
    { EGR_VLAN_XLATE_PARITY_STATUS_INTR_0r, NULL },
    { EGR_VLAN_XLATE_PARITY_STATUS_INTR_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_egr_vlan_xlate_nack_reg[] = {
    { EGR_VLAN_XLATE_PARITY_STATUS_NACK_0r, NULL },
    { EGR_VLAN_XLATE_PARITY_STATUS_NACK_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_vlan_xlate_intr_reg[] = {
    { VLAN_XLATE_PARITY_STATUS_INTR_0r, NULL },
    { VLAN_XLATE_PARITY_STATUS_INTR_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_vlan_xlate_nack_reg[] = {
    { VLAN_XLATE_PARITY_STATUS_NACK_0r, NULL },
    { VLAN_XLATE_PARITY_STATUS_NACK_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_mpls_entry_intr_reg[] = {
    { MPLS_ENTRY_PARITY_STATUS_INTR_0r, NULL },
    { MPLS_ENTRY_PARITY_STATUS_INTR_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_mpls_entry_nack_reg[] = {
    { MPLS_ENTRY_PARITY_STATUS_NACK_0r, NULL },
    { MPLS_ENTRY_PARITY_STATUS_NACK_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_l3_entry_only_intr_reg[] = {
    { L3_ENTRY_PARITY_STATUS_INTR_0r, NULL },
    { L3_ENTRY_PARITY_STATUS_INTR_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_l3_entry_only_nack_reg[] = {
    { L3_ENTRY_PARITY_STATUS_NACK_0r, NULL },
    { L3_ENTRY_PARITY_STATUS_NACK_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_l2_entry_only_intr_reg[] = {
    { L2_ENTRY_PARITY_STATUS_INTR_0r, NULL },
    { L2_ENTRY_PARITY_STATUS_INTR_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_l2_entry_only_nack_reg[] = {
    { L2_ENTRY_PARITY_STATUS_NACK_0r, NULL },
    { L2_ENTRY_PARITY_STATUS_NACK_1r, NULL } };
STATIC _soc_trident_parity_reg_t _soc_trident_pg5_fifo_intr_reg[] = {
    { PORT_GROUP5_XLP0_BOD_FIFO_ECC_STATUS_INTRr, "PG5 XLP0 BOD FIFO" },
    { PORT_GROUP5_XLP0_CTRL_FIFO_ECC_STATUS_INTRr, "PG5 XLP0 CTRL FIFO" },
    { PORT_GROUP5_XLP1_BOD_FIFO_ECC_STATUS_INTRr, "PG5 XLP1 BOD FIFO" },
    { PORT_GROUP5_XLP1_CTRL_FIFO_ECC_STATUS_INTRr, "PG5 XLP1 CTRL FIFO" },
    { PORT_GROUP5_XLP2_BOD_FIFO_ECC_STATUS_INTRr, "PG5 XLP2 BOD FIFO" },
    { PORT_GROUP5_XLP3_CTRL_FIFO_ECC_STATUS_INTRr, "PG5 XLP2 CTRL FIFO" },
    { PORT_GROUP5_XLP3_BOD_FIFO_ECC_STATUS_INTRr, "PG5 XLP3 BOD FIFO" },
    { PORT_GROUP5_XLP3_CTRL_FIFO_ECC_STATUS_INTRr, "PG5 XLP3 CTRL FIFO" },
    { PORT_GROUP5_XLP4_BOD_FIFO_ECC_STATUS_INTRr, "PG5 XLP4 BOD FIFO" },
    { PORT_GROUP5_XLP4_CTRL_FIFO_ECC_STATUS_INTRr, "PG5 XLP4 CTRL FIFO" },
    { INVALIDr } };
STATIC _soc_trident_parity_reg_t _soc_trident_pg4_fifo_intr_reg[] = {
    { PORT_GROUP4_XLP0_BOD_FIFO_ECC_STATUS_INTRr, "PG4 XLP0 BOD FIFO" },
    { PORT_GROUP4_XLP0_CTRL_FIFO_ECC_STATUS_INTRr, "PG4 XLP0 CTRL FIFO" },
    { PORT_GROUP4_XLP1_BOD_FIFO_ECC_STATUS_INTRr, "PG4 XLP1 BOD FIFO" },
    { PORT_GROUP4_XLP1_CTRL_FIFO_ECC_STATUS_INTRr, "PG4 XLP1 CTRL FIFO" },
    { PORT_GROUP4_XLP2_BOD_FIFO_ECC_STATUS_INTRr, "PG4 XLP2 BOD FIFO" },
    { PORT_GROUP4_XLP3_CTRL_FIFO_ECC_STATUS_INTRr, "PG4 XLP2 CTRL FIFO" },
    { PORT_GROUP4_XLP3_BOD_FIFO_ECC_STATUS_INTRr, "PG4 XLP3 BOD FIFO" },
    { PORT_GROUP4_XLP3_CTRL_FIFO_ECC_STATUS_INTRr, "PG4 XLP3 CTRL FIFO" },
    { INVALIDr } };

STATIC _soc_trident_parity_info_t _soc_trident_xlport_parity_info[] = {
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        TXFIFO_MEM_ERRf,
        TXFIFO_MEM_ERRf,
        INVALIDm, "TX FIFO",
        INVALIDr, INVALIDf,
        XLPORT_TXFIFO_MEM_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_TSC_MEM0_ERRf,
        MIB_TSC_MEM0_ERRf,
        INVALIDm, "TX MIB MEM0",
        INVALIDr, INVALIDf,
        XLPORT_MIB_TSC_MEM0_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_TSC_MEM1_ERRf,
        MIB_TSC_MEM1_ERRf,
        INVALIDm, "TX MIB MEM1",
        INVALIDr, INVALIDf,
        XLPORT_MIB_TSC_MEM1_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_TSC_MEM2_ERRf,
        MIB_TSC_MEM2_ERRf,
        INVALIDm, "TX MIB MEM2",
        INVALIDr, INVALIDf,
        XLPORT_MIB_TSC_MEM2_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_TSC_MEM3_ERRf,
        MIB_TSC_MEM3_ERRf,
        INVALIDm, "TX MIB MEM3",
        INVALIDr, INVALIDf,
        XLPORT_MIB_TSC_MEM3_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM0_ERRf,
        MIB_RSC_MEM0_ERRf,
        INVALIDm, "RX MIB MEM0",
        INVALIDr, INVALIDf,
        XLPORT_MIB_RSC_MEM0_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM1_ERRf,
        MIB_RSC_MEM1_ERRf,
        INVALIDm, "RX MIB MEM1",
        INVALIDr, INVALIDf,
        XLPORT_MIB_RSC_MEM1_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM2_ERRf,
        MIB_RSC_MEM2_ERRf,
        INVALIDm, "RX MIB MEM2",
        INVALIDr, INVALIDf,
        XLPORT_MIB_RSC_MEM2_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM3_ERRf,
        MIB_RSC_MEM3_ERRf,
        INVALIDm, "RX MIB MEM3",
        INVALIDr, INVALIDf,
        XLPORT_MIB_RSC_MEM3_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM4_ERRf,
        MIB_RSC_MEM4_ERRf,
        INVALIDm, "RX MIB MEM4",
        INVALIDr, INVALIDf,
        XLPORT_MIB_RSC_MEM4_ECC_STATUSr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_xlport1_parity_info[] = {
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        TXFIFO_MEM_ENf,
        TXFIFO_MEM_ENf,
        INVALIDm, "TX FIFO",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_TSC_MEM_ENf,
        MIB_TSC_MEM_ENf,
        INVALIDm, "TX FIFO",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        MIB_RSC_MEM_ENf,
        MIB_RSC_MEM_ENf,
        INVALIDm, "TX FIFO",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_mmu_parity_info[] = {
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        AGING_CTR_PAR_ERR_ENf,
        AGING_CTR_PAR_ERRf,
        INVALIDm, "MMU AGING CTR",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        AGING_EXP_PAR_ERR_ENf,
        AGING_EXP_PAR_ERRf,
        INVALIDm, "MMU AGING EXP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CCP_PAR_ERR_ENf,
        CCP_PAR_ERRf,
        INVALIDm, "MMU CCP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CFAP_PAR_ERR_ENf,
        CFAP_PAR_ERRf,
        INVALIDm, "MMU CFAP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CFAP_MEM_FAIL_ENf,
        CFAP_MEM_FAILf,
        INVALIDm, "MMU CFAP FAIL",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        DEQ_MPB_ERR_ENf,
        DEQ_MPB_ERRf,
        INVALIDm, "MMU DEQ MPB",
        MEM_FAIL_INT_ENr, DEQ_MPB_ERR_ENf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        DEQ_PKTHDR_ERR_ENf,
        DEQ_PKTHDR_ERRf,
        INVALIDm, "MMU DEQ PKTHDR",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        DEQ_NOT_IP_ERR_ENf,
        DEQ_NOT_IP_ERRf,
        INVALIDm, "MMU DEQ NOT IP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CTR_UC_CNT_ENf,
        CTR_UC_CNTf,
        INVALIDm, "MMU UC CNT",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        START_BY_START_ERR_ENf,
        START_BY_START_ERRf,
        INVALIDm, "MMU START BY START",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CTR_MC_CNT_ENf,
        CTR_MC_CNTf,
        INVALIDm, "MMU MC CNT",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        CTR_COLOR_CNT_ERR_ENf,
        CTR_COLOR_CNT_ERRf,
        INVALIDm, "MMU CTR COLOR CNT",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_UCQ_RP_PAR_ERR_ENf,
        TOQ0_UCQ_RP_PAR_ERRf,
        INVALIDm, "MMU UCQ RP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_UCQ_WP_PAR_ERR_ENf,
        TOQ0_UCQ_WP_PAR_ERRf,
        INVALIDm, "MMU UCQ WP",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_PKTLINK_PAR_ERR_ENf,
        TOQ0_PKTLINK_PAR_ERRf,
        INVALIDm, "MMU PKTLINK",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_CELLLINK_PAR_ERR_ENf,
        TOQ0_CELLLINK_PAR_ERRf,
        INVALIDm, "MMU CELLLINK",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_CPQLINK_PAR_ERR_ENf,
        TOQ0_CPQLINK_PAR_ERRf,
        INVALIDm, "MMU CPQLINK",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_IPMC_MC_FIFO_PAR_ERR_ENf,
        TOQ0_IPMC_MC_FIFO_PAR_ERRf,
        INVALIDm, "MMU IPMC MC FIFO",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_IPMC_TBL_PAR_ERR_ENf,
        TOQ0_IPMC_TBL_PAR_ERRf,
        INVALIDm, "MMU IPMC TBLI",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        TOQ0_VLAN_TBL_PAR_ERR_ENf,
        TOQ0_VLAN_TBL_PAR_ERRf,
        INVALIDm, "MMU VLAN TBL",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        MTRO_PAR_ERR_ENf,
        MTRO_PAR_ERRf,
        INVALIDm, "MMU MTRO PAR",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        WRED_PAR_ERR_ENf,
        WRED_PAR_ERRf,
        INVALIDm, "MMU WRED",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        OVQ_PAR_ERR_ENf,
        OVQ_PAR_ERRf,
        INVALIDm, "MMU OVQ",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        PQE_PAR_ERR_ENf,
        PQE_PAR_ERRf,
        INVALIDm, "MMU PQE PAR",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        QCN_PAR_ERR_ENf,
        QCN_PAR_ERRf,
        INVALIDm, "MMU QCN PAR",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_MMU_THDO, NULL, 0,
        THDO_PAR_ERR_ENf,
        THDO_PAR_ERRf,
        INVALIDm, "MMU THDO",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        THDI_PAR_ERR_ENf,
        THDI_PAR_ERRf,
        INVALIDm, "MMU THDI",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_GENERIC, NULL, 0,
        ES_PAR_ERR_ENf,
        ES_PAR_ERRf,
        INVALIDm, "MMU ES",
        INVALIDr, INVALIDf,
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ep0_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_NHOP_PAR_ERRf,
        EGR_NHOP_PAR_ERRf,
        EGR_L3_NEXT_HOPm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_L3_NEXT_HOP_PARITY_ENf,
        EGR_L3_NEXT_HOP_PARITY_STATUS_INTRr, NULL,
        EGR_L3_NEXT_HOP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_L3_INTF_PAR_ERRf,
        EGR_L3_INTF_PAR_ERRf,
        EGR_L3_INTFm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_L3_INTF_PARITY_ENf,
        EGR_L3_INTF_PARITY_STATUS_INTRr, NULL,
        EGR_L3_INTF_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MPLS_VC_AND_SWAP_LABEL_TABLE_PAR_ERRf,
        EGR_MPLS_VC_AND_SWAP_LABEL_TABLE_PAR_ERRf,
        EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_MPLS_VC_AND_SWAP_LABEL_TABLE_PARITY_ENf,
        EGR_MPLS_VC_AND_SWAP_LABEL_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_MPLS_VC_AND_SWAP_LABEL_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_VLAN_PAR_ERRf,
        EGR_VLAN_PAR_ERRf,
        EGR_VLANm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_VLAN_PARITY_ENf,
        EGR_VLAN_PARITY_STATUS_INTRr, NULL,
        EGR_VLAN_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_VLAN_STG_PAR_ERRf,
        EGR_VLAN_STG_PAR_ERRf,
        EGR_VLAN_STGm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_VLAN_STG_PARITY_ENf,
        EGR_VLAN_STG_PARITY_STATUS_INTRr, NULL,
        EGR_VLAN_STG_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_IP_TUNNEL_PAR_ERRf,
        EGR_IP_TUNNEL_PAR_ERRf,
        EGR_IP_TUNNELm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_IP_TUNNEL_PARITY_ENf,
        EGR_IP_TUNNEL_PARITY_STATUS_INTRr, NULL,
        EGR_IP_TUNNEL_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_HASH, NULL, 0,
        EGR_VLAN_XLATE_PAR_ERRf,
        EGR_VLAN_XLATE_PAR_ERRf,
        EGR_VLAN_XLATEm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_VLAN_XLATE_PARITY_ENf,
        INVALIDr, _soc_trident_egr_vlan_xlate_intr_reg,
        INVALIDr, _soc_trident_egr_vlan_xlate_nack_reg },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_FRAGMENT_ID_TABLE_PAR_ERRf,
        EGR_FRAGMENT_ID_TABLE_PAR_ERRf,
        EGR_FRAGMENT_ID_TABLEm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_FRAGMENT_ID_TABLE_PARITY_ENf,
        EGR_FRAGMENT_ID_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_FRAGMENT_ID_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        EGR_INITBUF_ECC_ERRf,
        EGR_INITBUF_ECC_ERRf,
        INVALIDm, "EGR_INITBUF",
        EGR_EHCPM_ECC_PARITY_CONTROLr, INITBUF_ECC_ENf,
        EGR_INITBUF_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_PORT_PAR_ERRf,
        EGR_PORT_PAR_ERRf,
        EGR_PORTm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_PORT_PARITY_ENf,
        EGR_PORT_PARITY_STATUS_INTRr, NULL,
        EGR_PORT_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_GPP_ATTRIBUTES_PAR_ERRf,
        EGR_GPP_ATTRIBUTES_PAR_ERRf,
        EGR_GPP_ATTRIBUTESm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_GPP_ATTRIBUTES_PARITY_ENf,
        EGR_GPP_ATTRIBUTES_PARITY_STATUS_INTRr, NULL,
        EGR_GPP_ATTRIBUTES_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MOD_MAP_TABLE_PAR_ERRf,
        EGR_MOD_MAP_TABLE_PAR_ERRf,
        EGR_MOD_MAP_TABLEm, NULL,
        EGR_EHCPM_ECC_PARITY_CONTROLr, MOD_MAP_PARITY_ENf,
        EGR_MOD_MAP_PARITY_STATUS_INTRr, NULL,
        EGR_MOD_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MAC_DA_PROFILE_PAR_ERRf,
        EGR_MAC_DA_PROFILE_PAR_ERRf,
        EGR_MAC_DA_PROFILEm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_MAC_DA_PROFILE_PARITY_ENf,
        EGR_MAC_DA_PROFILE_PARITY_STATUS_INTRr, NULL,
        EGR_MAC_DA_PROFILE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_DVP_ATTRIBUTE_PAR_ERRf,
        EGR_DVP_ATTRIBUTE_PAR_ERRf,
        EGR_DVP_ATTRIBUTEm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_DVP_ATTRIBUTE_PARITY_ENf,
        EGR_DVP_ATTRIBUTE_PARITY_STATUS_INTRr, NULL,
        EGR_DVP_ATTRIBUTE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_VFI_PAR_ERRf,
        EGR_VFI_PAR_ERRf,
        EGR_VFIm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_VFI_PARITY_ENf,
        EGR_VFI_PARITY_STATUS_INTRr, NULL,
        EGR_VFI_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_IPMC_PAR_ERRf,
        EGR_IPMC_PAR_ERRf,
        EGR_IPMCm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_IPMC_PARITY_ENf,
        EGR_IPMC_PARITY_STATUS_INTRr, NULL,
        EGR_IPMC_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MPLS_EXP_MAPPING_2_PAR_ERRf,
        EGR_MPLS_EXP_MAPPING_2_PAR_ERRf,
        EGR_MPLS_EXP_MAPPING_2m, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_MPLS_EXP_MAPPING_2_PARITY_ENf,
        EGR_MPLS_EXP_MAPPING_2_PARITY_STATUS_INTRr, NULL,
        EGR_MPLS_EXP_MAPPING_2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MPLS_PRI_MAPPING_PAR_ERRf,
        EGR_MPLS_PRI_MAPPING_PAR_ERRf,
        EGR_MPLS_PRI_MAPPINGm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_MPLS_PRI_MAPPING_PARITY_ENf,
        EGR_MPLS_PRI_MAPPING_PARITY_STATUS_INTRr, NULL,
        EGR_MPLS_PRI_MAPPING_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_PRI_CNG_MAP_PAR_ERRf,
        EGR_PRI_CNG_MAP_PAR_ERRf,
        EGR_PRI_CNG_MAPm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_PRI_CNG_MAP_PARITY_ENf,
        EGR_PRI_CNG_MAP_PARITY_STATUS_INTRr, NULL,
        EGR_PRI_CNG_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_DSCP_TABLE_PAR_ERRf,
        EGR_DSCP_TABLE_PAR_ERRf,
        EGR_DSCP_TABLEm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_DSCP_TABLE_PARITY_ENf,
        EGR_DSCP_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_DSCP_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        EGR_MPB_ECC_ERRf,
        EGR_MPB_ECC_ERRf,
        INVALIDm, "EGR_MPB",
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_MPB_ECC_ENf,
        EGR_MPB_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MAP_MH_PAR_ERRf,
        EGR_MAP_MH_PAR_ERRf,
        EGR_MAP_MHm, NULL,
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_MAP_MH_PARITY_ENf,
        EGR_MAP_MH_PARITY_STATUS_INTRr, NULL,
        EGR_MAP_MH_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_VLAN_CONTROL_1_PAR_ERRf,
        EGR_VLAN_CONTROL_1_PAR_ERRf,
        INVALIDm, "EGR_VLAN_CONTROL_1",
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_VLAN_CONTROL_1_PARITY_ENf,
        EGR_VLAN_CONTROL_1_PARITY_STATUS_INTRr, NULL,
        EGR_VLAN_CONTROL_1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_IPMC_CFG2_PAR_ERRf,
        EGR_IPMC_CFG2_PAR_ERRf,
        INVALIDm, "EGR_IPMC_CFG2",
        EGR_EL3_ECC_PARITY_CONTROLr, EGR_IPMC_CFG2_PARITY_ENf,
        EGR_IPMC_CFG2_PARITY_STATUS_INTRr, NULL,
        EGR_IPMC_CFG2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_GPP_ATTRIBUTES_MODBASE_PAR_ERRf,
        EGR_GPP_ATTRIBUTES_MODBASE_PAR_ERRf,
        EGR_GPP_ATTRIBUTES_MODBASEm, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_GPP_ATTRIBUTES_MODBASE_PARITY_ENf,
        EGR_GPP_ATTRIBUTES_MODBASE_PARITY_STATUS_INTRr, NULL,
        EGR_GPP_ATTRIBUTES_MODBASE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MPLS_EXP_MAPPING_1_PAR_ERRf,
        EGR_MPLS_EXP_MAPPING_1_PAR_ERRf,
        EGR_MPLS_EXP_MAPPING_1m, NULL,
        EGR_VLAN_PARITY_CONTROLr, EGR_MPLS_EXP_MAPPING_1_PARITY_ENf,
        EGR_MPLS_EXP_MAPPING_1_PARITY_STATUS_INTRr, NULL,
        EGR_MPLS_EXP_MAPPING_1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ep1_parity_info[] = {
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        CM_PAR_ERRf,
        CM_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_CM_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, CM_ECC_ENf,
        EGR_CM_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP0_PAR_ERRf,
        XLP0_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP0_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP0_ECC_ENf,
        EGR_XLP0_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP1_PAR_ERRf,
        XLP1_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP1_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP1_ECC_ENf,
        EGR_XLP1_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP2_PAR_ERRf,
        XLP2_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP2_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP2_ECC_ENf,
        EGR_XLP2_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP3_PAR_ERRf,
        XLP3_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP3_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP3_ECC_ENf,
        EGR_XLP3_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP4_PAR_ERRf,
        XLP4_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP4_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP4_ECC_ENf,
        EGR_XLP4_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP5_PAR_ERRf,
        XLP5_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP5_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP5_ECC_ENf,
        EGR_XLP5_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP6_PAR_ERRf,
        XLP6_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP6_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP6_ECC_ENf,
        EGR_XLP6_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP7_PAR_ERRf,
        XLP7_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP7_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP7_ECC_ENf,
        EGR_XLP7_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        XLP8_PAR_ERRf,
        XLP8_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_XLP8_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, XLP8_ECC_ENf,
        EGR_XLP8_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_EDATABUF, NULL, 0,
        LBP_PAR_ERRf,
        LBP_PAR_ERRf,
        INVALIDm, "EP_EDATABUF_LBP_MEM",
        EGR_EDATABUF_PARITY_CONTROLr, LBP_ECC_ENf,
        EGR_LBP_BUFFER_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        EGR_STATS_COUNTER_TABLE_PAR_ERRf,
        EGR_STATS_COUNTER_TABLE_PAR_ERRf,
        INVALIDm, "TX Debug Counter",
        EGR_EDATABUF_PARITY_CONTROLr, STATS_PAR_ENf,
        EGR_STATS_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_STATS_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_EFP_COUNTER_TABLE_PAR_ERRf,
        EGR_EFP_COUNTER_TABLE_PAR_ERRf,
        EFP_COUNTER_TABLEm, NULL,
        EGR_EDATABUF_PARITY_CONTROLr, EFPCTR_PAR_ENf,
        EGR_EFP_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_EFP_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_PERQ_XMT_COUNTERS_PAR_ERRf,
        EGR_PERQ_XMT_COUNTERS_PAR_ERRf,
        EGR_PERQ_XMT_COUNTERSm, NULL,
        EGR_EDATABUF_PARITY_CONTROLr, PERQ_PAR_ENf,
        EGR_PERQ_XMT_COUNTERS_PARITY_STATUS_INTRr, NULL,
        EGR_PERQ_XMT_COUNTERS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_PERQ_XMT_COUNTERS_BASE_ADDR_PAR_ERRf,
        EGR_PERQ_XMT_COUNTERS_BASE_ADDR_PAR_ERRf,
        EGR_PERQ_XMT_COUNTERS_BASE_ADDRm, NULL,
        EGR_EDATABUF_PARITY_CONTROLr, PERQ_BASE_ADDR_PAR_ENf,
        EGR_PERQ_XMT_COUNTERS_BASE_ADDR_PARITY_STATUS_INTRr, NULL,
        EGR_PERQ_XMT_COUNTERS_BASE_ADDR_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_VINTF_COUNTER_TABLE_PAR_ERRf,
        EGR_VINTF_COUNTER_TABLE_PAR_ERRf,
        EGR_VINTF_COUNTER_TABLEm, NULL,
        EGR_EDATABUF_PARITY_CONTROLr, VINTFCTR_PAR_ENf,
        EGR_VINTF_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_VINTF_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_SERVICE_COUNTER_TABLE_PAR_ERRf,
        EGR_SERVICE_COUNTER_TABLE_PAR_ERRf,
        EGR_SERVICE_COUNTER_TABLEm, NULL,
        EGR_EDATABUF_PARITY_CONTROLr, SVCCTR_PAR_ENf,
        EGR_SERVICE_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        EGR_SERVICE_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_EFP_METER_TABLE_PAR_ERRf,
        EGR_EFP_METER_TABLE_PAR_ERRf,
        EFP_METER_TABLEm, NULL,
        EFP_METER_PARITY_CONTROLr, PARITY_ENf,
        EFP_METER_PARITY_STATUS_INTRr, NULL,
        EFP_METER_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_EFP_POLICY_TABLE_PAR_ERRf,
        EGR_EFP_POLICY_TABLE_PAR_ERRf,
        EFP_POLICY_TABLEm, NULL,
        EFP_POLICY_PARITY_CONTROLr, PARITY_ENf,
        EFP_POLICY_PARITY_STATUS_INTRr, NULL,
        EFP_POLICY_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_EFP_PW_INIT_COUNTERS_PAR_ERRf,
        EGR_EFP_PW_INIT_COUNTERS_PAR_ERRf,
        EGR_PW_INIT_COUNTERSm, NULL,
        EGR_PW_INIT_COUNTERS_PARITY_CONTROLr, PARITY_ENf,
        EGR_PW_INIT_COUNTERS_PARITY_STATUS_INTRr, NULL,
        EGR_PW_INIT_COUNTERS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip0_parity_info[] = {
    /* IP0_INTR_STATUS.PPA_CMD_COMPLETE */
    /* IP0_INTR_STATUS.MEM_RESET_COMPLETE */
    /* IP0_INTR_STATUS.AGE_CMD_COMPLETE */
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        LMEP_PAR_ERRf,
        LMEP_PAR_ERRf,
        LMEPm, NULL,
        LMEP_PARITY_CONTROLr, PARITY_ENf,
        LMEP_PARITY_STATUS_INTRr, NULL,
        LMEP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        IARB_PKT_ERRf,
        IARB_PKT_ERRf,
        INVALIDm, "IARB_PKT_BUF",
        IARB_PKT_ECC_CONTROLr, ECC_ENf,
        IARB_PKT_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        IARB_HDR_ERRf,
        IARB_HDR_ERRf,
        INVALIDm, "IARB_PKT_HDR",
        IARB_HDR_ECC_CONTROLr, ECC_ENf,
        IARB_HDR_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        IARB_PIPE_X_LERAN_FIFO_ECC_ERRf,
        IARB_PIPE_X_LERAN_FIFO_ECC_ERRf,
        INVALIDm, "IARB_LERAN_FIFO_PIPE_X",
        IARB_LEARN_FIFO_ECC_CONTROLr, ECC_ENf,
        IARB_PIPE_X_LERAN_FIFO_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        IARB_PIPE_Y_LERAN_FIFO_ECC_ERRf,
        IARB_PIPE_Y_LERAN_FIFO_ECC_ERRf,
        INVALIDm, "IARB_LERAN_FIFO_PIPE_Y",
        IARB_LEARN_FIFO_ECC_CONTROLr, ECC_ENf,
        IARB_PIPE_Y_LERAN_FIFO_ECC_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip1_parity_info[] = {
    { _SOC_PARITY_TYPE_HASH, NULL, 0,
        VXLT_PAR_ERRf,
        VXLT_PAR_ERRf,
        VLAN_XLATEm, NULL,
        VLAN_XLATE_PARITY_CONTROLr, PARITY_ENf,
        INVALIDr, _soc_trident_vlan_xlate_intr_reg,
        INVALIDr, _soc_trident_vlan_xlate_nack_reg },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VFP_POLICY_PAR_ERRf,
        VFP_POLICY_PAR_ERRf,
        VFP_POLICY_TABLEm, NULL,
        VFP_POLICY_PARITY_CONTROLr, PARITY_ENf,
        VFP_POLICY_PARITY_STATUS_INTRr, NULL,
        VFP_POLICY_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_PROT_PAR_ERRf,
        VLAN_PROT_PAR_ERRf,
        VLAN_PROTOCOL_DATAm, NULL,
        VLAN_PROT_PARITY_CONTROLr, PARITY_ENf,
        VLAN_PROT_PARITY_STATUS_INTRr, NULL,
        VLAN_PROT_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_SUBNET_PAR_ERRf,
        VLAN_SUBNET_PAR_ERRf,
        VLAN_SUBNET_DATA_ONLYm, NULL,
        VLAN_SUBNET_PARITY_CONTROLr, PARITY_ENf,
        VLAN_SUBNET_PARITY_STATUS_INTRr, NULL,
        VLAN_SUBNET_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        CPU_TS_POLICY_PAR_ERRf,
        CPU_TS_POLICY_PAR_ERRf,
        CPU_TS_MAPm, NULL,
        CPU_TS_PARITY_CONTROLr, PARITY_ENf,
        CPU_TS_PARITY_STATUS_INTRr, NULL,
        CPU_TS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_RANGE_PAR_ERRf,
        VLAN_RANGE_PAR_ERRf,
        ING_VLAN_RANGEm, NULL,
        VLAN_RANGE_PARITY_CONTROLr, PARITY_ENf,
        VLAN_RANGE_PARITY_STATUS_INTRr, NULL,
        VLAN_RANGE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MOD_MAP_PAR_ERRf,
        MOD_MAP_PAR_ERRf,
        ING_MOD_MAP_TABLEm, NULL,
        MOD_MAP_PARITY_CONTROLr, PARITY_ENf,
        MOD_MAP_PARITY_STATUS_INTRr, NULL,
        MOD_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        FP_UDF_PAR_ERRf,
        FP_UDF_PAR_ERRf,
        FP_UDF_OFFSETm, NULL,
        FP_UDF_PARITY_CONTROLr, PARITY_ENf,
        FP_UDF_PARITY_STATUS_INTRr, NULL,
        FP_UDF_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_TUNNEL_PAR_ERRf,
        L3_TUNNEL_PAR_ERRf,
        L3_TUNNELm, NULL,
        L3_TUNNEL_PARITY_CONTROLr, PARITY_ENf,
        L3_TUNNEL_PARITY_STATUS_INTRr, NULL,
        L3_TUNNEL_PARITY_STATUS_NACKr, NULL },
    /* IP1_INTR_STATUS.WLAN_SVP_PAR_ERR */
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        SRC_TRUNK_PAR_ERRf,
        SRC_TRUNK_PAR_ERRf,
        SOURCE_TRUNK_MAP_TABLEm, NULL,
        SRC_TRUNK_ECC_CONTROLr, ECC_ENf,
        SRC_TRUNK_ECC_STATUS_INTRr, NULL,
        SRC_TRUNK_ECC_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        LPORT_PAR_ERRf,
        LPORT_PAR_ERRf,
        LPORT_TABm, NULL,
        LPORT_ECC_CONTROLr, ECC_ENf,
        LPORT_ECC_STATUS_INTRr, NULL,
        LPORT_ECC_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_HASH, NULL, 0,
        MPLS_ENTRY_PAR_ERRf,
        MPLS_ENTRY_PAR_ERRf,
        MPLS_ENTRYm, NULL,
        MPLS_ENTRY_PARITY_CONTROLr, PARITY_ENf,
        INVALIDr, _soc_trident_mpls_entry_intr_reg,
        INVALIDr, _soc_trident_mpls_entry_nack_reg },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        PORT_TABLE_PAR_ERRf,
        PORT_TABLE_PAR_ERRf,
        PORT_TABm, NULL,
        PORT_TABLE_ECC_CONTROLr, ECC_ENf,
        PORT_TABLE_ECC_STATUS_INTRr, NULL,
        PORT_TABLE_ECC_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SYS_CONFIG_PAR_ERRf,
        SYS_CONFIG_PAR_ERRf,
        SYSTEM_CONFIG_TABLEm, NULL,
        SYSTEM_CONFIG_PARITY_CONTROLr, PARITY_ENf,
        SYSTEM_CONFIG_PARITY_STATUS_INTRr, NULL,
        SYSTEM_CONFIG_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SYSTEM_CONFIG_MODVIEW_PAR_ERRf,
        SYSTEM_CONFIG_MODVIEW_PAR_ERRf,
        SYSTEM_CONFIG_TABLE_MODBASEm, NULL,
        SYSTEM_CONFIG_MODVIEW_PARITY_CONTROLr, PARITY_ENf,
        SYSTEM_CONFIG_MODVIEW_PARITY_STATUS_INTRr, NULL,
        SYSTEM_CONFIG_MODVIEW_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SOURCE_TRUNK_MAP_MODVIEW_PAR_ERRf,
        SOURCE_TRUNK_MAP_MODVIEW_PAR_ERRf,
        SOURCE_TRUNK_MAP_MODBASEm, NULL,
        SOURCE_TRUNK_MAP_MODVIEW_PARITY_CONTROLr, PARITY_ENf,
        SOURCE_TRUNK_MAP_MODVIEW_PARITY_STATUS_INTRr, NULL,
        SOURCE_TRUNK_MAP_MODVIEW_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip2_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        NHOP_PAR_ERRf,
        NHOP_PAR_ERRf,
        INITIAL_ING_L3_NEXT_HOPm, NULL,
        INITIAL_ING_L3_NEXT_HOP_PARITY_CONTROLr, PARITY_ENf,
        INITIAL_ING_L3_NEXT_HOP_PARITY_STATUS_INTRr, NULL,
        INITIAL_ING_L3_NEXT_HOP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ECMP_GRP_PAR_ERRf,
        ECMP_GRP_PAR_ERRf,
        INITIAL_L3_ECMP_GROUPm, NULL,
        INITIAL_L3_ECMP_GROUP_PARITY_CONTROLr, PARITY_ENf,
        INITIAL_L3_ECMP_GROUP_PARITY_STATUS_INTRr, NULL,
        INITIAL_L3_ECMP_GROUP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_ECMP_PAR_ERRf,
        L3_ECMP_PAR_ERRf,
        INITIAL_L3_ECMPm, NULL,
        INITIAL_L3_ECMP_PARITY_CONTROLr, PARITY_ENf,
        INITIAL_L3_ECMP_PARITY_STATUS_INTRr, NULL,
        INITIAL_L3_ECMP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_DVP_PAR_ERRf,
        ING_DVP_PAR_ERRf,
        ING_DVP_TABLEm, NULL,
        ING_DVP_TABLE_PARITY_CONTROLr, PARITY_ENf,
        ING_DVP_TABLE_PARITY_STATUS_INTRr, NULL,
        ING_DVP_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        PROT_NHI_PAR_ERRf,
        PROT_NHI_PAR_ERRf,
        INITIAL_PROT_NHI_TABLEm, NULL,
        INITIAL_PROT_NHI_TABLE_PARITY_CONTROLr, PARITY_ENf,
        INITIAL_PROT_NHI_TABLE_PARITY_STATUS_INTRr, NULL,
        INITIAL_PROT_NHI_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        PORT_CBL_PAR_ERRf,
        PORT_CBL_PAR_ERRf,
        PORT_CBL_TABLEm, NULL,
        PORT_CBL_TABLE_PARITY_CONTROLr, PARITY_ENf,
        PORT_CBL_TABLE_PARITY_STATUS_INTRr, NULL,
        PORT_CBL_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        PORT_CBL_MODBASE_PAR_ERRf,
        PORT_CBL_MODBASE_PAR_ERRf,
        PORT_CBL_TABLE_MODBASEm, NULL,
        PORT_CBL_TABLE_MODBASE_PARITY_CONTROLr, PARITY_ENf,
        PORT_CBL_TABLE_MODBASE_PARITY_STATUS_INTRr, NULL,
        PORT_CBL_TABLE_MODBASE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_IPMC_1_PAR_ERRf,
        L3_IPMC_1_PAR_ERRf,
        L3_IPMC_1m, NULL,
        L3_IPMC_1_PARITY_CONTROLr, PARITY_ENf,
        L3_IPMC_1_PARITY_STATUS_INTRr, NULL,
        L3_IPMC_1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MA_INDEX_PAR_ERRf,
        MA_INDEX_PAR_ERRf,
        MA_INDEXm, NULL,
        MA_INDEX_PARITY_CONTROLr, PARITY_ENf,
        MA_INDEX_PARITY_STATUS_INTRr, NULL,
        MA_INDEX_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        RMEP_PAR_ERRf,
        RMEP_PAR_ERRf,
        RMEPm, NULL,
        RMEP_PARITY_CONTROLr, PARITY_ENf,
        RMEP_PARITY_STATUS_INTRr, NULL,
        RMEP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MAID_REDUCTION_PAR_ERRf,
        MAID_REDUCTION_PAR_ERRf,
        MAID_REDUCTIONm, NULL,
        MAID_REDUCTION_PARITY_CONTROLr, PARITY_ENf,
        MAID_REDUCTION_PARITY_STATUS_INTRr, NULL,
        MAID_REDUCTION_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MA_STATE_PAR_ERRf,
        MA_STATE_PAR_ERRf,
        MA_STATEm, NULL,
        MA_STATE_PARITY_CONTROLr, PARITY_ENf,
        MA_STATE_PARITY_STATUS_INTRr, NULL,
        MA_STATE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_PAR_ERRf,
        VLAN_PAR_ERRf,
        VLAN_TABm, NULL,
        VLAN_PARITY_CONTROLr, PARITY_ENf,
        VLAN_PARITY_STATUS_INTRr, NULL,
        VLAN_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SVP_PAR_ERRf,
        SVP_PAR_ERRf,
        SOURCE_VPm, NULL,
        SOURCE_VP_PARITY_CONTROLr, PARITY_ENf,
        SOURCE_VP_PARITY_STATUS_INTRr, NULL,
        SOURCE_VP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_IIF_PAR_ERRf,
        L3_IIF_PAR_ERRf,
        L3_IIFm, NULL,
        L3_IIF_PARITY_CONTROLr, PARITY_ENf,
        L3_IIF_PARITY_STATUS_INTRr, NULL,
        L3_IIF_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VFI_INTRf,
        VFI_INTRf,
        VFIm, NULL,
        VFI_PARITY_CONTROLr, PARITY_ENf,
        VFI_PARITY_STATUS_INTRr, NULL,
        VFI_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_MPLS_INTRf,
        VLAN_MPLS_INTRf,
        VLAN_MPLSm, NULL,
        VLAN_MPLS_PARITY_CONTROLr, PARITY_ENf,
        VLAN_MPLS_PARITY_STATUS_INTRr, NULL,
        VLAN_MPLS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_STG_INTRf,
        VLAN_STG_INTRf,
        STG_TABm, NULL,
        VLAN_STG_PARITY_CONTROLr, PARITY_ENf,
        VLAN_STG_PARITY_STATUS_INTRr, NULL,
        VLAN_STG_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VRF_INTRf,
        VRF_INTRf,
        VRFm, NULL,
        VRF_PARITY_CONTROLr, PARITY_ENf,
        VRF_PARITY_STATUS_INTRr, NULL,
        VRF_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VFI_1_INTRf,
        VFI_1_INTRf,
        VFI_1m, NULL,
        VFI_1_PARITY_CONTROLr, PARITY_ENf,
        VFI_1_PARITY_STATUS_INTRr, NULL,
        VFI_1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_HASH, NULL, 0,
        L3_ENTRY_PAR_ERRf,
        L3_ENTRY_PAR_ERRf,
        L3_ENTRY_ONLYm, NULL,
        L3_ENTRY_PARITY_CONTROLr, PARITY_ENf,
        INVALIDr, _soc_trident_l3_entry_only_intr_reg,
        INVALIDr, _soc_trident_l3_entry_only_nack_reg },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_DEFIP_DATA_PAR_ERRf,
        L3_DEFIP_DATA_PAR_ERRf,
        L3_DEFIP_DATA_ONLYm, NULL,
        L3_DEFIP_DATA_PARITY_CONTROLr, PARITY_ENf,
        L3_DEFIP_DATA_PARITY_STATUS_INTRr, NULL,
        L3_DEFIP_DATA_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_DEFIP_128_DATA_PAR_ERRf,
        L3_DEFIP_128_DATA_PAR_ERRf,
        L3_DEFIP_128_DATA_ONLYm, NULL,
        L3_DEFIP_128_DATA_PARITY_CONTROLr, PARITY_ENf,
        L3_DEFIP_128_DATA_PARITY_STATUS_INTRr, NULL,
        L3_DEFIP_128_DATA_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TTL_FN_PAR_ERRf,
        TTL_FN_PAR_ERRf,
        TTL_FNm, NULL,
        TTL_FN_PARITY_CONTROLr, PARITY_ENf,
        TTL_FN_PARITY_STATUS_INTRr, NULL,
        TTL_FN_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TOS_FN_PAR_ERRf,
        TOS_FN_PAR_ERRf,
        TOS_FNm, NULL,
        TOS_FN_PARITY_CONTROLr, PARITY_ENf,
        TOS_FN_PARITY_STATUS_INTRr, NULL,
        TOS_FN_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_PRI_CNG_MAP_PAR_ERRf,
        ING_PRI_CNG_MAP_PAR_ERRf,
        ING_PRI_CNG_MAPm, NULL,
        ING_PRI_CNG_MAP_PARITY_CONTROLr, PARITY_ENf,
        ING_PRI_CNG_MAP_PARITY_STATUS_INTRr, NULL,
        ING_PRI_CNG_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_UNTAGGED_PHB_PAR_ERRf,
        ING_UNTAGGED_PHB_PAR_ERRf,
        ING_UNTAGGED_PHBm, NULL,
        ING_UNTAGGED_PHB_PARITY_CONTROLr, PARITY_ENf,
        ING_UNTAGGED_PHB_PARITY_STATUS_INTRr, NULL,
        ING_UNTAGGED_PHB_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        DSCP_TABLE_PAR_ERRf,
        DSCP_TABLE_PAR_ERRf,
        DSCP_TABLEm, NULL,
        DSCP_TABLE_PARITY_CONTROLr, PARITY_ENf,
        DSCP_TABLE_PARITY_STATUS_INTRr, NULL,
        DSCP_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        FP_FIELD_SEL_PAR_ERRf,
        FP_FIELD_SEL_PAR_ERRf,
        FP_PORT_FIELD_SELm, NULL,
        FP_FIELD_SEL_PARITY_CONTROLr, PARITY_ENf,
        FP_FIELD_SEL_PARITY_STATUS_INTRr, NULL,
        FP_FIELD_SEL_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip2_2_parity_info[] = {
    /* IP2_INTR_STATUS_2.SOME_RDI_DEFECT_INTR */
    /* IP2_INTR_STATUS_2.SOME_RMEP_CCM_DEFECT_INTR */
    /* IP2_INTR_STATUS_2.ERROR_CCM_DEFECT_INTR */
    /* IP2_INTR_STATUS_2.ANY_RMEP_TLV_PORT_DOWN_INTR */
    /* IP2_INTR_STATUS_2.ANY_RMEP_TLV_PORT_UP_INTR */
    /* IP2_INTR_STATUS_2.ANY_RMEP_TLV_INTERFACE_DOWN_INTR */
    /* IP2_INTR_STATUS_2.ANY_RMEP_TLV_INTERFACE_UP_INTR */
    /* IP2_INTR_STATUS_2.XCON_CCM_DEFECT_INTR */
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip3_parity_info[] = {
    { _SOC_PARITY_TYPE_HASH, NULL, 0,
        L2_ENTRY_PAR_ERRf,
        L2_ENTRY_PAR_ERRf,
        L2_ENTRY_ONLYm, NULL,
        L2_ENTRY_PARITY_CONTROLr, PARITY_ENf,
        INVALIDr, _soc_trident_l2_entry_only_intr_reg,
        INVALIDr, _soc_trident_l2_entry_only_nack_reg },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L2_MOD_FIFO_INTRf,
        L2_MOD_FIFO_INTRf,
        L2_MOD_FIFOm, NULL,
        L2_MOD_FIFO_PARITY_CONTROLr, PARITY_ENf,
        L2_MOD_FIFO_PARITY_STATUS_INTRr, NULL,
        L2_MOD_FIFO_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L2_USER_ENTRY_DATA_INTRf,
        L2_USER_ENTRY_DATA_INTRf,
        L2_USER_ENTRY_DATA_ONLYm, NULL,
        L2_USER_ENTRY_DATA_PARITY_CONTROLr, PARITY_ENf,
        L2_USER_ENTRY_DATA_PARITY_STATUS_INTRr, NULL,
        L2_USER_ENTRY_DATA_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip4_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_POLICY_PAR_ERRf,
        IFP_POLICY_PAR_ERRf,
        FP_POLICY_TABLEm, NULL,
        IFP_POLICY_PARITY_CONTROLr, PARITY_ENf,
        IFP_POLICY_PARITY_STATUS_INTRr, NULL,
        IFP_POLICY_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_STORM_CONTROL_PAR_ERRf,
        IFP_STORM_CONTROL_PAR_ERRf,
        FP_STORM_CONTROL_METERSm, NULL,
        IFP_STORM_CONTROL_PARITY_CONTROLr, PARITY_ENf,
        IFP_STORM_CONTROL_PARITY_STATUS_INTRr, NULL,
        IFP_STORM_CONTROL_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_COUNTER_PAR_ERRf,
        IFP_COUNTER_PAR_ERRf,
        FP_COUNTER_TABLEm, NULL,
        IFP_COUNTER_PARITY_CONTROLr, PARITY_ENf,
        IFP_COUNTER_PARITY_STATUS_INTRr, NULL,
        IFP_COUNTER_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_METER_PAR_ERRf,
        IFP_METER_PAR_ERRf,
        FP_METER_TABLEm, NULL,
        IFP_METER_PARITY_CONTROLr, PARITY_ENf,
        IFP_METER_PARITY_STATUS_INTRr, NULL,
        IFP_METER_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_ING_DVP_2_PAR_ERRf,
        IFP_ING_DVP_2_PAR_ERRf,
        ING_DVP_2_TABLEm, NULL,
        IFP_ING_DVP_2_PARITY_CONTROLr, PARITY_ENf,
        IFP_ING_DVP_2_PARITY_STATUS_INTRr, NULL,
        IFP_ING_DVP_2_PARITY_STATUS_NACKr, NULL },
#if 0 /* Do not enable parity since there is no simple way to clear these
       * 2 memory buffers during init */
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_METER_MUX_DATA_STAGING_PAR_ERRf,
        IFP_METER_MUX_DATA_STAGING_PAR_ERRf,
        INVALIDm, "IFP_METER_MUX_DATA_STAGING",
        IFP_METER_MUX_DATA_STAGING_PARITY_CONTROLr, PARITY_ENf,
        IFP_METER_MUX_DATA_STAGING_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IFP_COUNTER_MUX_DATA_STAGING_PAR_ERRf,
        IFP_COUNTER_MUX_DATA_STAGING_PAR_ERRf,
        INVALIDm, "IFP_COUNTER_MUX_DATA_STAGING",
        IFP_COUNTER_MUX_DATA_STAGING_PARITY_CONTROLr, PARITY_ENf,
        IFP_COUNTER_MUX_DATA_STAGING_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
#endif
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_EGR_MASK_MODBASE_PAR_ERRf,
        IRSEL2_EGR_MASK_MODBASE_PAR_ERRf,
        EGR_MASK_MODBASEm, NULL,
        EGR_MASK_MODBASE_PARITY_CONTROLr, PARITY_ENf,
        EGR_MASK_MODBASE_PARITY_STATUS_INTRr, NULL,
        EGR_MASK_MODBASE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_ICONTROL_OPCODE_BITMAP_PAR_ERRf,
        IRSEL2_ICONTROL_OPCODE_BITMAP_PAR_ERRf,
        ICONTROL_OPCODE_BITMAPm, NULL,
        ICONTROL_OPCODE_BITMAP_PARITY_CONTROLr, PARITY_ENf,
        ICONTROL_OPCODE_BITMAP_PARITY_STATUS_INTRr, NULL,
        ICONTROL_OPCODE_BITMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_IFP_REDIRECTION_PROFILE_PAR_ERRf,
        IRSEL2_IFP_REDIRECTION_PROFILE_PAR_ERRf,
        IFP_REDIRECTION_PROFILEm, NULL,
        IFP_REDIRECTION_PROFILE_PARITY_CONTROLr, PARITY_ENf,
        IFP_REDIRECTION_PROFILE_PARITY_STATUS_INTRr, NULL,
        IFP_REDIRECTION_PROFILE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_ING_L3_NEXT_HOP_PAR_ERRf,
        IRSEL2_ING_L3_NEXT_HOP_PAR_ERRf,
        ING_L3_NEXT_HOPm, NULL,
        ING_L3_NEXT_HOP_PARITY_CONTROLr, PARITY_ENf,
        ING_L3_NEXT_HOP_PARITY_STATUS_INTRr, NULL,
        ING_L3_NEXT_HOP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_L2MC_PAR_ERRf,
        IRSEL2_L2MC_PAR_ERRf,
        L2MCm, NULL,
        L2MC_PARITY_CONTROLr, PARITY_ENf,
        L2MC_PARITY_STATUS_INTRr, NULL,
        L2MC_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_L3_ECMP_GROUP_PAR_ERRf,
        IRSEL2_L3_ECMP_GROUP_PAR_ERRf,
        L3_ECMP_COUNTm, NULL,
        L3_ECMP_GROUP_PARITY_CONTROLr, PARITY_ENf,
        L3_ECMP_GROUP_PARITY_STATUS_INTRr, NULL,
        L3_ECMP_GROUP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_L3_ECMP_PAR_ERRf,
        IRSEL2_L3_ECMP_PAR_ERRf,
        L3_ECMPm, NULL,
        L3_ECMP_PARITY_CONTROLr, PARITY_ENf,
        L3_ECMP_PARITY_STATUS_INTRr, NULL,
        L3_ECMP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_L3_IPMC_PAR_ERRf,
        IRSEL2_L3_IPMC_PAR_ERRf,
        L3_IPMCm, NULL,
        L3_IPMC_PARITY_CONTROLr, PARITY_ENf,
        L3_IPMC_PARITY_STATUS_INTRr, NULL,
        L3_IPMC_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_L3_IPMC_REMAP_PAR_ERRf,
        IRSEL2_L3_IPMC_REMAP_PAR_ERRf,
        L3_IPMC_REMAPm, NULL,
        L3_IPMC_REMAP_PARITY_CONTROLr, PARITY_ENf,
        L3_IPMC_REMAP_PARITY_STATUS_INTRr, NULL,
        L3_IPMC_REMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IRSEL2_TRUNK_GROUP_PAR_ERRf,
        IRSEL2_TRUNK_GROUP_PAR_ERRf,
        TRUNK_GROUPm, NULL,
        TRUNK_GROUP_PARITY_CONTROLr, PARITY_ENf,
        TRUNK_GROUP_PARITY_STATUS_INTRr, NULL,
        TRUNK_GROUP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip5_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VOQ_COS_MAP_PAR_ERRf,
        VOQ_COS_MAP_PAR_ERRf,
        VOQ_COS_MAPm, NULL,
        VOQ_COS_MAP_PARITY_CONTROLr, PARITY_ENf,
        VOQ_COS_MAP_PARITY_STATUS_INTRr, NULL,
        VOQ_COS_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        DLB_HGT_FLOWSET_PORT_PAR_ERRf,
        DLB_HGT_FLOWSET_PORT_PAR_ERRf,
        DLB_HGT_FLOWSET_PORTm, NULL,
        DLB_HGT_FLOWSET_PORT_PARITY_CONTROLr, PARITY_ENf,
        DLB_HGT_FLOWSET_PORT_PARITY_STATUS_INTRr, NULL,
        DLB_HGT_FLOWSET_PORT_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        DLB_HGT_FLOWSET_TIMESTAMP_PAR_ERRf,
        DLB_HGT_FLOWSET_TIMESTAMP_PAR_ERRf,
        DLB_HGT_FLOWSET_TIMESTAMPm, NULL,
        DLB_HGT_FLOWSET_TIMESTAMP_PARITY_CONTROLr, PARITY_ENf,
        DLB_HGT_FLOWSET_TIMESTAMP_PARITY_STATUS_INTRr, NULL,
        DLB_HGT_FLOWSET_TIMESTAMP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGE_PAR_ERRf,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGE_PAR_ERRf,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGEm, NULL,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGE_PARITY_CONTROLr, PARITY_ENf,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGE_PARITY_STATUS_INTRr, NULL,
        DLB_HGT_FLOWSET_TIMESTAMP_PAGE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip5_1_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EGR_MASK_PAR_ERRf,
        EGR_MASK_PAR_ERRf,
        EGR_MASKm, NULL,
        EGR_MASK_PARITY_CONTROLr, PARITY_ENf,
        EGR_MASK_PARITY_STATUS_INTRr, NULL,
        EGR_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TRUNK_BITMAP_PAR_ERRf,
        TRUNK_BITMAP_PAR_ERRf,
        TRUNK_BITMAPm, NULL,
        TRUNK_BITMAP_TABLE_PARITY_CONTROLr, PARITY_ENf,
        TRUNK_BITMAP_TABLE_PARITY_STATUS_INTRr, NULL,
        TRUNK_BITMAP_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        NONUCAST_TRUNK_BLOCK_MASK_PAR_ERRf,
        NONUCAST_TRUNK_BLOCK_MASK_PAR_ERRf,
        NONUCAST_TRUNK_BLOCK_MASKm, NULL,
        NONUCAST_TRUNK_BLOCK_MASK_PARITY_CONTROLr, PARITY_ENf,
        NONUCAST_TRUNK_BLOCK_MASK_PARITY_STATUS_INTRr, NULL,
        NONUCAST_TRUNK_BLOCK_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MAC_BLOCK_TABLE_PAR_ERRf,
        MAC_BLOCK_TABLE_PAR_ERRf,
        MAC_BLOCKm, NULL,
        MAC_BLOCK_TABLE_PARITY_CONTROLr, PARITY_ENf,
        MAC_BLOCK_TABLE_PARITY_STATUS_INTRr, NULL,
        MAC_BLOCK_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MODPORT_MAP_SW_PAR_ERRf,
        MODPORT_MAP_SW_PAR_ERRf,
        MODPORT_MAP_SWm, NULL,
        MODPORT_MAP_SW_PARITY_CONTROLr, PARITY_ENf,
        MODPORT_MAP_SW_PARITY_STATUS_INTRr, NULL,
        MODPORT_MAP_SW_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MODPORT_MAP_M0_PAR_ERRf,
        MODPORT_MAP_M0_PAR_ERRf,
        MODPORT_MAP_M0m, NULL,
        MODPORT_MAP_MIRROR_PARITY_CONTROLr, PARITY_ENf,
        MODPORT_MAP_M0_PARITY_STATUS_INTRr, NULL,
        MODPORT_MAP_M0_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MODPORT_MAP_M1_PAR_ERRf,
        MODPORT_MAP_M1_PAR_ERRf,
        MODPORT_MAP_M1m, NULL,
        MODPORT_MAP_MIRROR_PARITY_CONTROLr, PARITY_ENf,
        MODPORT_MAP_M1_PARITY_STATUS_INTRr, NULL,
        MODPORT_MAP_M1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MODPORT_MAP_M2_PAR_ERRf,
        MODPORT_MAP_M2_PAR_ERRf,
        MODPORT_MAP_M2m, NULL,
        MODPORT_MAP_MIRROR_PARITY_CONTROLr, PARITY_ENf,
        MODPORT_MAP_M2_PARITY_STATUS_INTRr, NULL,
        MODPORT_MAP_M2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        MODPORT_MAP_M3_PAR_ERRf,
        MODPORT_MAP_M3_PAR_ERRf,
        MODPORT_MAP_M3m, NULL,
        MODPORT_MAP_MIRROR_PARITY_CONTROLr, PARITY_ENf,
        MODPORT_MAP_M3_PARITY_STATUS_INTRr, NULL,
        MODPORT_MAP_M3_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SRC_MODID_INGRESS_BLOCK_PAR_ERRf,
        SRC_MODID_INGRESS_BLOCK_PAR_ERRf,
        SRC_MODID_INGRESS_BLOCKm, NULL,
        SRC_MODID_INGRESS_BLOCK_PARITY_CONTROLr, PARITY_ENf,
        SRC_MODID_INGRESS_BLOCK_PARITY_STATUS_INTRr, NULL,
        SRC_MODID_INGRESS_BLOCK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SRC_MODID_EGRESS_PAR_ERRf,
        SRC_MODID_EGRESS_PAR_ERRf,
        SRC_MODID_EGRESSm, NULL,
        SRC_MODID_EGRESS_PARITY_CONTROLr, PARITY_ENf,
        SRC_MODID_EGRESS_PARITY_STATUS_INTRr, NULL,
        SRC_MODID_EGRESS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ALTERNATE_EMIRROR_BITMAP_PAR_ERRf,
        ALTERNATE_EMIRROR_BITMAP_PAR_ERRf,
        ALTERNATE_EMIRROR_BITMAPm, NULL,
        ALTERNATE_EMIRROR_BITMAP_PARITY_CONTROLr, PARITY_ENf,
        ALTERNATE_EMIRROR_BITMAP_PARITY_STATUS_INTRr, NULL,
        ALTERNATE_EMIRROR_BITMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        PORT_LAG_FAILOVER_SET_PAR_ERRf,
        PORT_LAG_FAILOVER_SET_PAR_ERRf,
        PORT_LAG_FAILOVER_SETm, NULL,
        PORT_LAG_FAILOVER_SET_PARITY_CONTROLr, PARITY_ENf,
        PORT_LAG_FAILOVER_SET_PARITY_STATUS_INTRr, NULL,
        PORT_LAG_FAILOVER_SET_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_PROFILE_2_PAR_ERRf,
        VLAN_PROFILE_2_PAR_ERRf,
        VLAN_PROFILE_2m, NULL,
        VLAN_PROFILE_2_PARITY_CONTROLr, PARITY_ENf,
        VLAN_PROFILE_2_PARITY_STATUS_INTRr, NULL,
        VLAN_PROFILE_2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        L3_MTU_VALUES_PAR_ERRf,
        L3_MTU_VALUES_PAR_ERRf,
        L3_MTU_VALUESm, NULL,
        L3_MTU_VALUES_PARITY_CONTROLr, PARITY_ENf,
        L3_MTU_VALUES_PARITY_STATUS_INTRr, NULL,
        L3_MTU_VALUES_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_PW_TERM_SEQ_NUM_PAR_ERRf,
        ING_PW_TERM_SEQ_NUM_PAR_ERRf,
        ING_PW_TERM_SEQ_NUMm, NULL,
        ING_PW_TERM_SEQ_NUM_PARITY_CONTROLr, PARITY_ENf,
        ING_PW_TERM_SEQ_NUM_PARITY_STATUS_INTRr, NULL,
        ING_PW_TERM_SEQ_NUM_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_SERVICE_COUNTER_TABLE_PAR_ERRf,
        ING_SERVICE_COUNTER_TABLE_PAR_ERRf,
        ING_SERVICE_COUNTER_TABLEm, NULL,
        ING_SERVICE_COUNTER_TABLE_PARITY_CONTROLr, PARITY_ENf,
        ING_SERVICE_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        ING_SERVICE_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_VINTF_COUNTER_TABLE_PAR_ERRf,
        ING_VINTF_COUNTER_TABLE_PAR_ERRf,
        ING_VINTF_COUNTER_TABLEm, NULL,
        ING_VINTF_COUNTER_TABLE_PARITY_CONTROLr, PARITY_ENf,
        ING_VINTF_COUNTER_TABLE_PARITY_STATUS_INTRr, NULL,
        ING_VINTF_COUNTER_TABLE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        VLAN_COS_MAP_PAR_ERRf,
        VLAN_COS_MAP_PAR_ERRf,
        VLAN_COS_MAPm, NULL,
        VLAN_COS_MAP_PARITY_CONTROLr, PARITY_ENf,
        VLAN_COS_MAP_PARITY_STATUS_INTRr, NULL,
        VLAN_COS_MAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        E2E_HOL_STATUS_PAR_ERRf,
        E2E_HOL_STATUS_PAR_ERRf,
        E2E_HOL_STATUSm, NULL,
        E2E_HOL_STATUS_PARITY_CONTROLr, PARITY_ENf,
        E2E_HOL_STATUS_PARITY_STATUS_INTRr, NULL,
        E2E_HOL_STATUS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        E2E_HOL_STATUS_1_PAR_ERRf,
        E2E_HOL_STATUS_1_PAR_ERRf,
        E2E_HOL_STATUS_1m, NULL,
        E2E_HOL_STATUS_1_PARITY_CONTROLr, PARITY_ENf,
        E2E_HOL_STATUS_1_PARITY_STATUS_INTRr, NULL,
        E2E_HOL_STATUS_1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        UNKNOWN_UCAST_BLOCK_MASK_PAR_ERRf,
        UNKNOWN_UCAST_BLOCK_MASK_PAR_ERRf,
        UNKNOWN_UCAST_BLOCK_MASKm, NULL,
        UNKNOWN_UCAST_BLOCK_MASK_PARITY_CONTROLr, PARITY_ENf,
        UNKNOWN_UCAST_BLOCK_MASK_PARITY_STATUS_INTRr, NULL,
        UNKNOWN_UCAST_BLOCK_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        UNKNOWN_MCAST_BLOCK_MASK_PAR_ERRf,
        UNKNOWN_MCAST_BLOCK_MASK_PAR_ERRf,
        UNKNOWN_MCAST_BLOCK_MASKm, NULL,
        UNKNOWN_MCAST_BLOCK_MASK_PARITY_CONTROLr, PARITY_ENf,
        UNKNOWN_MCAST_BLOCK_MASK_PARITY_STATUS_INTRr, NULL,
        UNKNOWN_MCAST_BLOCK_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        BCAST_BLOCK_MASK_PAR_ERRf,
        BCAST_BLOCK_MASK_PAR_ERRf,
        BCAST_BLOCK_MASKm, NULL,
        BCAST_BLOCK_MASK_PARITY_CONTROLr, PARITY_ENf,
        BCAST_BLOCK_MASK_PARITY_STATUS_INTRr, NULL,
        BCAST_BLOCK_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        KNOWN_MCAST_BLOCK_MASK_PAR_ERRf,
        KNOWN_MCAST_BLOCK_MASK_PAR_ERRf,
        KNOWN_MCAST_BLOCK_MASKm, NULL,
        KNOWN_MCAST_BLOCK_MASK_PARITY_CONTROLr, PARITY_ENf,
        KNOWN_MCAST_BLOCK_MASK_PARITY_STATUS_INTRr, NULL,
        KNOWN_MCAST_BLOCK_MASK_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_EGRMSKBMAP_PAR_ERRf,
        ING_EGRMSKBMAP_PAR_ERRf,
        ING_EGRMSKBMAPm, NULL,
        ING_EGRMSKBMAP_PARITY_CONTROLr, PARITY_ENf,
        ING_EGRMSKBMAP_PARITY_STATUS_INTRr, NULL,
        ING_EGRMSKBMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        LOCAL_SW_DISABLE_DEFAULT_PBM_PAR_ERRf,
        LOCAL_SW_DISABLE_DEFAULT_PBM_PAR_ERRf,
        LOCAL_SW_DISABLE_DEFAULT_PBMm, NULL,
        LOCAL_SW_DISABLE_DEFAULT_PBM_PARITY_CONTROLr, PARITY_ENf,
        LOCAL_SW_DISABLE_DEFAULT_PBM_PARITY_STATUS_INTRr, NULL,
        LOCAL_SW_DISABLE_DEFAULT_PBM_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRR_PAR_ERRf,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRR_PAR_ERRf,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRRm, NULL,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRR_PARITY_CONTROLr, PARITY_ENf,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRR_PARITY_STATUS_INTRr, NULL,
        LOCAL_SW_DISABLE_DEFAULT_PBM_MIRR_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        IMIRROR_BITMAP_PAR_ERRf,
        IMIRROR_BITMAP_PAR_ERRf,
        IMIRROR_BITMAPm, NULL,
        IMIRROR_BITMAP_PARITY_CONTROLr, PARITY_ENf,
        IMIRROR_BITMAP_PARITY_STATUS_INTRr, NULL,
        IMIRROR_BITMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        UNKNOWN_HGI_BITMAP_PAR_ERRf,
        UNKNOWN_HGI_BITMAP_PAR_ERRf,
        UNKNOWN_HGI_BITMAPm, NULL,
        UNKNOWN_HGI_BITMAP_PARITY_CONTROLr, PARITY_ENf,
        UNKNOWN_HGI_BITMAP_PARITY_STATUS_INTRr, NULL,
        UNKNOWN_HGI_BITMAP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TRUNK_MEMBER_PAR_ERRf,
        TRUNK_MEMBER_PAR_ERRf,
        TRUNK_MEMBERm, NULL,
        TRUNK_MEMBER_PARITY_CONTROLr, PARITY_ENf,
        TRUNK_MEMBER_PARITY_STATUS_INTRr, NULL,
        TRUNK_MEMBER_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILE_PAR_ERRf,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILE_PAR_ERRf,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, NULL,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILE_PARITY_CONTROLr, PARITY_ENf,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILE_PARITY_STATUS_INTRr, NULL,
        ING_HIGIG_TRUNK_OVERRIDE_PROFILE_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_ip5_2_parity_info[] = {
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EMIRROR_CONTROL_PAR_ERRf,
        EMIRROR_CONTROL_PAR_ERRf,
        EMIRROR_CONTROLm, NULL,
        EMIRROR_CONTROL_PARITY_CONTROLr, PARITY_ENf,
        EMIRROR_CONTROL_PARITY_STATUS_INTRr, NULL,
        EMIRROR_CONTROL_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EMIRROR_CONTROL1_PAR_ERRf,
        EMIRROR_CONTROL1_PAR_ERRf,
        EMIRROR_CONTROL1m, NULL,
        EMIRROR_CONTROL1_PARITY_CONTROLr, PARITY_ENf,
        EMIRROR_CONTROL1_PARITY_STATUS_INTRr, NULL,
        EMIRROR_CONTROL1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EMIRROR_CONTROL2_PAR_ERRf,
        EMIRROR_CONTROL2_PAR_ERRf,
        EMIRROR_CONTROL2m, NULL,
        EMIRROR_CONTROL2_PARITY_CONTROLr, PARITY_ENf,
        EMIRROR_CONTROL2_PARITY_STATUS_INTRr, NULL,
        EMIRROR_CONTROL2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        EMIRROR_CONTROL3_PAR_ERRf,
        EMIRROR_CONTROL3_PAR_ERRf,
        EMIRROR_CONTROL3m, NULL,
        EMIRROR_CONTROL3_PARITY_CONTROLr, PARITY_ENf,
        EMIRROR_CONTROL3_PARITY_STATUS_INTRr, NULL,
        EMIRROR_CONTROL3_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SW2_EOP_BUFFER_A_PAR_ERRf,
        SW2_EOP_BUFFER_A_PAR_ERRf,
        INVALIDm, "SW2_EOP_BUFFER_A",
        SW2_EOP_BUFFER_A_PARITY_CONTROLr, PARITY_ENf,
        SW2_EOP_BUFFER_A_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SW2_EOP_BUFFER_B_PAR_ERRf,
        SW2_EOP_BUFFER_B_PAR_ERRf,
        INVALIDm, "SW2_EOP_BUFFER_B",
        SW2_EOP_BUFFER_B_PARITY_CONTROLr, PARITY_ENf,
        SW2_EOP_BUFFER_B_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        SW2_EOP_BUFFER_C_PAR_ERRf,
        SW2_EOP_BUFFER_C_PAR_ERRf,
        INVALIDm, "SW2_EOP_BUFFER_C",
        SW2_EOP_BUFFER_C_PARITY_CONTROLr, PARITY_ENf,
        SW2_EOP_BUFFER_C_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        IP_COUNTERS_PAR_ERRf,
        IP_COUNTERS_PAR_ERRf,
        INVALIDm, "Ingress Pipeline Counter",
        IP_COUNTERS_PARITY_CONTROLr, PARITY_ENf,
        IP_COUNTERS_PARITY_STATUS_INTRr, NULL,
        IP_COUNTERS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        RDBGC_MEM_INST0_PAR_ERRf,
        RDBGC_MEM_INST0_PAR_ERRf,
        INVALIDm, "Ingress Pipeline Counter",
        RDBGC_MEM_INST0_PARITY_CONTROLr, PARITY_ENf,
        RDBGC_MEM_INST0_PARITY_STATUS_INTRr, NULL,
        RDBGC_MEM_INST0_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        RDBGC_MEM_INST1_PAR_ERRf,
        RDBGC_MEM_INST1_PAR_ERRf,
        INVALIDm, "RX Debug Counter",
        RDBGC_MEM_INST1_PARITY_CONTROLr, PARITY_ENf,
        RDBGC_MEM_INST1_PARITY_STATUS_INTRr, NULL,
        RDBGC_MEM_INST1_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        RDBGC_MEM_INST2_PAR_ERRf,
        RDBGC_MEM_INST2_PAR_ERRf,
        INVALIDm, "RX Debug Counter",
        RDBGC_MEM_INST2_PARITY_CONTROLr, PARITY_ENf,
        RDBGC_MEM_INST2_PARITY_STATUS_INTRr, NULL,
        RDBGC_MEM_INST2_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_COUNTER, NULL, 0,
        HG_COUNTERS_PAR_ERRf,
        HG_COUNTERS_PAR_ERRf,
        INVALIDm, "Ingress Pipeline HG Counter",
        HG_COUNTERS_PARITY_CONTROLr, PARITY_ENf,
        HG_COUNTERS_PARITY_STATUS_INTRr, NULL,
        HG_COUNTERS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        NIV_ERROR_DROP_PAR_ERRf,
        NIV_ERROR_DROP_PAR_ERRf,
        INVALIDm, "ING_NIV_RX_FRAMES_ERROR_DROP",
        NIV_ERROR_DROP_PARITY_CONTROLr, PARITY_ENf,
        NIV_ERROR_DROP_PARITY_STATUS_INTRr, NULL,
        NIV_ERROR_DROP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        NIV_FORWARDING_DROP_PAR_ERRf,
        NIV_FORWARDING_DROP_PAR_ERRf,
        INVALIDm, "ING_NIV_RX_FRAMES_FORWARDING_DROP",
        NIV_FORWARDING_DROP_PARITY_CONTROLr, PARITY_ENf,
        NIV_FORWARDING_DROP_PARITY_STATUS_INTRr, NULL,
        NIV_FORWARDING_DROP_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        NIV_VLAN_TAGGED_PAR_ERRf,
        NIV_VLAN_TAGGED_PAR_ERRf,
        INVALIDm, "ING_NIV_RX_FRAMES_VLAN_TAGGED",
        NIV_VLAN_TAGGED_PARITY_CONTROLr, PARITY_ENf,
        NIV_VLAN_TAGGED_PARITY_STATUS_INTRr, NULL,
        NIV_VLAN_TAGGED_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TRILL_RX_PKTS_PAR_ERRf,
        TRILL_RX_PKTS_PAR_ERRf,
        INVALIDm, "ING_TRILL_RX_PKTS",
        TRILL_RX_PKTS_PARITY_CONTROLr, PARITY_ENf,
        TRILL_RX_PKTS_PARITY_STATUS_INTRr, NULL,
        TRILL_RX_PKTS_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED_PAR_ERRf,
        TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED_PAR_ERRf,
        INVALIDm, "ING_TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED",
        TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED_PARITY_CONTROLr, PARITY_ENf,
        TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED_PARITY_STATUS_INTRr, NULL,
        TRILL_RX_ACCESS_PORT_TRILL_PKTS_DISCARDED_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED_PAR_ERRf,
        TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED_PAR_ERRf,
        INVALIDm, "ING_TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED",
        TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED_PARITY_CONTROLr, PARITY_ENf,
        TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED_PARITY_STATUS_INTRr, NULL,
        TRILL_RX_NETWORK_PORT_NON_TRILL_PKTS_DISCARDED_PARITY_STATUS_NACKr, NULL },
    { _SOC_PARITY_TYPE_PARITY, NULL, 0,
        CPB_PAR_ERRf,
        CPB_PAR_ERRf,
        INVALIDm, "CPB",
        CPB_PARITY_CONTROLr, PARITY_ENf,
        CPB_PARITY_STATUS_INTRr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_pg5_parity_info[] = {
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 0,
        XLP0_PERR_INTRf,
        XLP0_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 0,
        XLP0_PERR_INTRf,
        XLP0_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 1,
        XLP1_PERR_INTRf,
        XLP1_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 1,
        XLP1_PERR_INTRf,
        XLP1_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 2,
        XLP2_PERR_INTRf,
        XLP2_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 2,
        XLP2_PERR_INTRf,
        XLP2_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 3,
        XLP3_PERR_INTRf,
        XLP3_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 3,
        XLP3_PERR_INTRf,
        XLP3_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 4,
        XLP4_PERR_INTRf,
        XLP4_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 4,
        XLP4_PERR_INTRf,
        XLP4_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        PG5_PERR_INTRf,
        PG5_PERR_INTRf,
        INVALIDm, "PG5 FIFO",
        PORT_GROUP5_BOD_FIFO_ECC_ENABLEr, BOD_FIFO_ECC_ENABLEf,
        INVALIDr, _soc_trident_pg5_fifo_intr_reg,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC _soc_trident_parity_info_t _soc_trident_pg4_parity_info[] = {
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 5,
        XLP0_PERR_INTRf,
        XLP0_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 5,
        XLP0_PERR_INTRf,
        XLP0_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 6,
        XLP1_PERR_INTRf,
        XLP1_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 6,
        XLP1_PERR_INTRf,
        XLP1_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 7,
        XLP2_PERR_INTRf,
        XLP2_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 7,
        XLP2_PERR_INTRf,
        XLP2_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport_parity_info, 8,
        XLP3_PERR_INTRf,
        XLP3_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_INTR_ENABLEr, INVALIDf, /* group enable */
        XLPORT_INTR_STATUSr, NULL,     /* group status */
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_XLPORT, _soc_trident_xlport1_parity_info, 8,
        XLP3_PERR_INTRf,
        XLP3_PERR_INTRf,
        INVALIDm, "XLPORT",
        XLPORT_ECC_CONTROLr, INVALIDf, /* group enable */
        INVALIDr, NULL,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_ECC, NULL, 0,
        PG4_PERR_INTRf,
        PG4_PERR_INTRf,
        INVALIDm, "PG4 FIFO",
        PORT_GROUP4_BOD_FIFO_ECC_ENABLEr, BOD_FIFO_ECC_ENABLEf,
        INVALIDr, _soc_trident_pg4_fifo_intr_reg,
        INVALIDr, NULL },
    { _SOC_PARITY_TYPE_NONE } /* table terminator */
};

STATIC const
_soc_trident_parity_route_block_t  _soc_trident_parity_route_blocks[] = {
    { 0x00000001, /* MMU_TO_CMIC_MEMFAIL_INTR */
        SOC_BLK_MMU, -1, MEM_FAIL_INT_ENr, MEM_FAIL_INT_STATr,
        _soc_trident_mmu_parity_info },
    { 0x00000002, /* X_EP1_TO_CMIC_PERR_INTR */
        SOC_BLK_EPIPE, 0, EGR_INTR0_ENABLEr, EGR_INTR0_STATUSr,
        _soc_trident_ep0_parity_info },
    { 0x00000004, /* Y_EP1_TO_CMIC_PERR_INTR */
        SOC_BLK_EPIPE, 1, EGR_INTR0_ENABLEr, EGR_INTR0_STATUSr,
        _soc_trident_ep0_parity_info },
    { 0x00000008, /* X_EP2_TO_CMIC_PERR_INTR */
        SOC_BLK_EPIPE, 0, EGR_INTR1_ENABLEr, EGR_INTR1_STATUSr,
        _soc_trident_ep1_parity_info },
    { 0x00000010, /* Y_EP2_TO_CMIC_PERR_INTR */
        SOC_BLK_EPIPE, 1, EGR_INTR1_ENABLEr, EGR_INTR1_STATUSr,
        _soc_trident_ep1_parity_info },
    { 0x00000020, /* X_IP0_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP0_INTR_ENABLEr, IP0_INTR_STATUSr,
        _soc_trident_ip0_parity_info },
    { 0x00000040, /* Y_IP0_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP0_INTR_ENABLEr, IP0_INTR_STATUSr,
        _soc_trident_ip0_parity_info },
    { 0x00000080, /* X_IP1_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP1_INTR_ENABLEr, IP1_INTR_STATUSr,
        _soc_trident_ip1_parity_info },
    { 0x00000100, /* Y_IP1_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP1_INTR_ENABLEr, IP1_INTR_STATUSr,
        _soc_trident_ip1_parity_info },
    { 0x00000200, /* X_IP2_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP2_INTR_ENABLEr, IP2_INTR_STATUSr,
        _soc_trident_ip2_parity_info },
    { 0x00000200, /* X_IP2_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP2_INTR_ENABLE_2r, IP2_INTR_STATUS_2r,
        _soc_trident_ip2_2_parity_info },
    { 0x00000400, /* Y_IP2_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP2_INTR_ENABLEr, IP2_INTR_STATUSr,
        _soc_trident_ip2_parity_info },
    { 0x00000400, /* Y_IP2_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP2_INTR_ENABLE_2r, IP2_INTR_STATUS_2r,
        _soc_trident_ip2_2_parity_info },
    { 0x00000800, /* X_IP3_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP3_INTR_ENABLEr, IP3_INTR_STATUSr,
        _soc_trident_ip3_parity_info },
    { 0x00001000, /* Y_IP3_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP3_INTR_ENABLEr, IP3_INTR_STATUSr,
        _soc_trident_ip3_parity_info },
    { 0x00002000, /* X_IP4_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP4_INTR_ENABLEr, IP4_INTR_STATUSr,
        _soc_trident_ip4_parity_info },
    { 0x00004000, /* Y_IP4_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP4_INTR_ENABLEr, IP4_INTR_STATUSr,
        _soc_trident_ip4_parity_info },
    { 0x00008000, /* X_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP5_INTR_ENABLEr, IP5_INTR_STATUSr,
        _soc_trident_ip5_parity_info },
    { 0x00008000, /* X_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP5_INTR_ENABLE_1r, IP5_INTR_STATUS_1r,
        _soc_trident_ip5_1_parity_info },
    { 0x00008000, /* X_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 0, IP5_INTR_ENABLE_2r, IP5_INTR_STATUS_2r,
        _soc_trident_ip5_2_parity_info },
    { 0x00010000, /* Y_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP5_INTR_ENABLEr, IP5_INTR_STATUSr,
        _soc_trident_ip5_parity_info },
    { 0x00010000, /* Y_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP5_INTR_ENABLE_1r, IP5_INTR_STATUS_1r,
        _soc_trident_ip5_1_parity_info },
    { 0x00010000, /* Y_IP5_TO_CMIC_PERR_INTR */
        SOC_BLK_IPIPE, 1, IP5_INTR_ENABLE_2r, IP5_INTR_STATUS_2r,
        _soc_trident_ip5_2_parity_info },
    /*  0x00020000 PCIE_REPLAY_PERR */
    { 0x00040000, /* PG5_0_TO_CMIC_PERR_INTR */
        SOC_BLK_PORT_GROUP5, 0, PG5_INTR_ENABLEr, PG5_INTR_STATUSr,
        _soc_trident_pg5_parity_info },
    { 0x00080000, /* PG5_1_TO_CMIC_PERR_INTR */
        SOC_BLK_PORT_GROUP5, 1, PG5_INTR_ENABLEr, PG5_INTR_STATUSr,
        _soc_trident_pg5_parity_info },
    { 0x00100000, /* PG4_0_TO_CMIC_PERR_INTR */
        SOC_BLK_PORT_GROUP4, 0, PG4_INTR_ENABLEr, PG4_INTR_STATUSr,
        _soc_trident_pg4_parity_info },
    { 0x00200000, /* PG4_1_TO_CMIC_PERR_INTR */
        SOC_BLK_PORT_GROUP4, 1, PG4_INTR_ENABLEr, PG4_INTR_STATUSr,
        _soc_trident_pg4_parity_info },
    { 0 } /* table terminator */
};

STATIC int
_soc_trident_parity_reg_set(int unit, int block_info_idx, int pipe,
                            soc_reg_t reg, uint32 rval)
{
    int rv, egress, port;

    switch (SOC_BLOCK_INFO(unit, block_info_idx).type) {
    case SOC_BLK_IPIPE:
        egress = 0;
        port = REG_PORT_ANY;
        break;
    case SOC_BLK_EPIPE:
        egress = 1;
        port = REG_PORT_ANY;
        break;
    case SOC_BLK_PORT_GROUP4:
    case SOC_BLK_PORT_GROUP5:
        egress = -1;
        port = pipe;
        break;
    default:
        egress = -1;
        port = REG_PORT_ANY;
        break;
    }

    if (egress != -1) {
        SOC_IF_ERROR_RETURN(soc_trident_pipe_select(unit, egress, pipe));
    }

    rv = soc_reg32_set(unit, reg, port, 0, rval);

    if (egress != -1) {
        (void)soc_trident_pipe_select(unit, egress, 0);
    }

    return rv;
}

STATIC int
_soc_trident_parity_reg_get(int unit, int block_info_idx, int pipe,
                            soc_reg_t reg, uint32 *rval)
{
    int rv, egress, port;

    switch (SOC_BLOCK_INFO(unit, block_info_idx).type) {
    case SOC_BLK_IPIPE:
        egress = 0;
        port = REG_PORT_ANY;
        break;
    case SOC_BLK_EPIPE:
        egress = 1;
        port = REG_PORT_ANY;
        break;
    case SOC_BLK_PORT_GROUP4:
    case SOC_BLK_PORT_GROUP5:
        egress = -1;
        port = pipe;
        break;
    default:
        egress = -1;
        port = REG_PORT_ANY;
        break;
    }

    if (egress != -1) {
        SOC_IF_ERROR_RETURN(soc_trident_pipe_select(unit, egress, pipe));
    }

    rv = soc_reg32_get(unit, reg, port, 0, rval);

    if (egress != -1) {
        (void)soc_trident_pipe_select(unit, egress, 0);
    }

    return rv;
}

STATIC int
_soc_trident_parity_enable_info(int unit, int block_info_idx, int pipe,
                                soc_reg_t group_reg, uint32 *group_rval,
                                const _soc_trident_parity_info_t *info_list,
                                soc_mem_t mem, int enable);

STATIC int
_soc_trident_parity_enable_xlport(int unit, int pipe,
                                  const _soc_trident_parity_info_t *info,
                                  soc_mem_t mem, int enable)
{
    soc_reg_t xlport_reg;
    uint32 xlport_rval;
    int block_info_idx, inst_num, port;

    port = -1;
    inst_num = info->id + pipe * 9;
    SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
        if (SOC_BLOCK_INFO(unit, block_info_idx).number == inst_num) {
            port = SOC_BLOCK_PORT(unit, block_info_idx);
            break;
        }
    }
    if (port < 0) {
        return SOC_E_NONE;
    }

    xlport_reg = info->enable_reg;
    SOC_IF_ERROR_RETURN
        (soc_reg32_get(unit, xlport_reg, port, 0, &xlport_rval));

    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_enable_info(unit, block_info_idx, pipe,
                                         xlport_reg, &xlport_rval,
                                         info->info, mem, enable));

    SOC_IF_ERROR_RETURN(soc_reg32_set(unit, xlport_reg, port, 0, xlport_rval));

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_enable_info(int unit, int block_info_idx, int pipe,
                                soc_reg_t group_reg, uint32 *group_rval,
                                const _soc_trident_parity_info_t *info_list,
                                soc_mem_t mem,
                                int enable)
{
    const _soc_trident_parity_info_t *info;
    int info_index, rv, rv1;
    soc_reg_t reg;
    uint32 rval;

    rv = SOC_E_NOT_FOUND;

    /* Loop through each info entry in the list */
    for (info_index = 0; ; info_index++) {
        info = &info_list[info_index];
        if (info->type == _SOC_PARITY_TYPE_NONE) {
            /* End of table */
            break;
        }

        if (mem != INVALIDm && info->mem != mem) {
            continue;
        }

        rv = SOC_E_NONE;

        /* Enable the info entry in the group register */
        soc_reg_field_set(unit, group_reg, group_rval,
                          info->group_reg_enable_field, enable ? 1 : 0);

        /* Handle different parity error reporting style */
        switch (info->type) {
        case _SOC_PARITY_TYPE_PARITY:
        case _SOC_PARITY_TYPE_ECC:
        case _SOC_PARITY_TYPE_HASH:
        case _SOC_PARITY_TYPE_EDATABUF:
        case _SOC_PARITY_TYPE_COUNTER:
            reg = info->enable_reg;
            if (!SOC_REG_IS_VALID(unit, reg)) {
                break;
            }
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg,
                                             &rval));
            soc_reg_field_set(unit, reg, &rval, info->enable_field,
                              enable ? 1 : 0);
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg,
                                             rval));
            break;
        case _SOC_PARITY_TYPE_XLPORT:
            /* One more level of report tree structure */
            rv1 = _soc_trident_parity_enable_xlport(unit, pipe, info, mem,
                                                    enable);
            if (SOC_FAILURE(rv1) && rv1 != SOC_E_NOT_FOUND) {
                return rv;
            }
            break;
        case _SOC_PARITY_TYPE_GENERIC:
        case _SOC_PARITY_TYPE_MMU_THDO:
        default:
            break;
        } /* Handle different parity error reporting style */
        if (mem != INVALIDm) {
            break;
        }

    } /* Loop through each info entry in the route block */

    return rv;
}

STATIC int
_soc_trident_parity_enable_all(int unit, int enable)
{
    const _soc_trident_parity_route_block_t *route_block;
    int route_block_index;
    uint32 rval;
    uint32 cmic_rval, route_block_rval;
    uint32 cmic_bit;
    int block_info_idx, inst_num;
    int rv;
    uint16 dev_id, drv_dev_id;
    uint8 rev_id, drv_rev_id;

    soc_cm_get_id(unit, &dev_id, &rev_id);
    soc_cm_get_id_driver(dev_id, rev_id, &drv_dev_id, &drv_rev_id);

    /* Read CMIC enable register */
    SOC_IF_ERROR_RETURN(READ_CMIC_CHIP_PARITY_INTR_ENABLEr(unit, &cmic_rval));

    /* Loop through each place-and-route block entry */
    for (route_block_index = 0; ; route_block_index++) {
        route_block = &_soc_trident_parity_route_blocks[route_block_index];
        cmic_bit = route_block->cmic_bit;
        if (cmic_bit == 0) {
            /* End of table */
            break;
        }
        /* Enable the route block entry in the CMIC register */
        if (enable) {
            cmic_rval |= cmic_bit;
        }

        if (route_block->blocktype == SOC_BLK_PORT_GROUP4 ||
            route_block->blocktype == SOC_BLK_PORT_GROUP5) {
            inst_num = route_block->pipe;
        } else {
            inst_num = 0;
        }
        SOC_BLOCK_ITER(unit, block_info_idx, route_block->blocktype) {
            if (SOC_BLOCK_INFO(unit, block_info_idx).number == inst_num) {
                break;
            }
        }

        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         &route_block_rval));

        rv = _soc_trident_parity_enable_info(unit, block_info_idx,
                                             route_block->pipe,
                                             route_block->enable_reg,
                                             &route_block_rval,
                                             route_block->info, INVALIDm,
                                             enable);
        if (rv == SOC_E_NOT_FOUND) {
            continue;
        } else if (SOC_FAILURE(rv)) {
            return rv;
        }

        /* Write per route block parity enable register */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         route_block_rval));
    } /* Loop through each place-and-route block entry */

    /* Write CMIC enable register */
    SOC_IF_ERROR_RETURN(WRITE_CMIC_CHIP_PARITY_INTR_ENABLEr(unit, cmic_rval));

    /* MMU enables */
    SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_STAT_CLEARf, 1);
    SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));

    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_CHK_ENf, 1);
    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_GEN_ENf, 1);
    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_STAT_CLEARf, 0);
    SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));

    SOC_IF_ERROR_RETURN(READ_MEM_FAIL_INT_STATr(unit, &rval));

    if (!(drv_rev_id == BCM56840_A0_REV_ID && rev_id == BCM56840_A0_REV_ID)) {
        /* Do not serve interrupt for Trident A0 */
        soc_intr_enable(unit, IRQ_MEM_FAIL);
    }

    return SOC_E_NONE;
}

int
_soc_trident_mem_parity_control(int unit, soc_mem_t mem, int copyno,
                                int enable)
{
    const _soc_trident_parity_route_block_t *route_block;
    int route_block_index;
    uint32 rval;
    uint32 cmic_rval, route_block_rval;
    uint32 cmic_bit;
    int block_info_idx, inst_num;
    int rv;

    SOC_IF_ERROR_RETURN(READ_CMIC_CHIP_PARITY_INTR_ENABLEr(unit, &cmic_rval));
    if (cmic_rval == 0) {
        return SOC_E_NONE;
    }

    /* Convert component/aggregate memories to the table for which
     * the parity registers correspond. */
    switch(mem) {
    case MY_STATION_TCAMm:
        mem = MY_STATION_TCAM_DATA_ONLYm;
        break;

        /* ep0 */
    case EGR_IP_TUNNEL_IPV6m:
    case EGR_IP_TUNNEL_MPLSm:
        mem = EGR_IP_TUNNELm;
        break;
    case EGR_FRAGMENT_ID_TABLE_Xm:
    case EGR_FRAGMENT_ID_TABLE_Ym:
        mem = EGR_FRAGMENT_ID_TABLEm;
        break;

        /* ep1 */
    case EFP_COUNTER_TABLE_Xm:
    case EFP_COUNTER_TABLE_Ym:
        mem = EFP_COUNTER_TABLEm;
        break;
    case EGR_PERQ_XMT_COUNTERS_Xm:
    case EGR_PERQ_XMT_COUNTERS_Ym:
        mem = EGR_PERQ_XMT_COUNTERSm;
        break;
    case EGR_VINTF_COUNTER_TABLE_Xm:
    case EGR_VINTF_COUNTER_TABLE_Ym:
        mem = EGR_VINTF_COUNTER_TABLEm;
        break;
    case EGR_SERVICE_COUNTER_TABLE_Xm:
    case EGR_SERVICE_COUNTER_TABLE_Ym:
        mem = EGR_SERVICE_COUNTER_TABLEm;
        break;
    case EFP_METER_TABLE_Xm:
    case EFP_METER_TABLE_Ym:
        mem = EFP_METER_TABLEm;
        break;
    case EGR_PW_INIT_COUNTERS_Xm:
    case EGR_PW_INIT_COUNTERS_Ym:
        mem = EGR_PW_INIT_COUNTERSm;
        break;

        /* ip0 */

        /* ip1 */
    case VLAN_MACm:
        mem = VLAN_XLATEm;
        break;
    case VLAN_SUBNETm:
        mem = VLAN_SUBNET_DATA_ONLYm;
        break;

        /* ip2 */
    case L3_ENTRY_IPV4_UNICASTm:
    case L3_ENTRY_IPV4_MULTICASTm:
    case L3_ENTRY_IPV6_UNICASTm:
    case L3_ENTRY_IPV6_MULTICASTm:
        mem = L3_ENTRY_ONLYm;
        break;
    case L3_DEFIPm:
        mem = L3_DEFIP_DATA_ONLYm;
        break;
    case L3_DEFIP_128m:
        mem = L3_DEFIP_128_DATA_ONLYm;
        break;

        /* ip2_2 */

        /* ip3 */
    case L2Xm:
        mem = L2_ENTRY_ONLYm;
        break;
    case L2_USER_ENTRYm:
        mem = L2_USER_ENTRY_DATA_ONLYm;
        break;

        /* ip4 */
    case FP_COUNTER_TABLE_Xm:
    case FP_COUNTER_TABLE_Ym:
        mem = FP_COUNTER_TABLEm;
        break;

        /* ip5 */
    case DLB_HGT_FLOWSET_PORT_Xm:
    case DLB_HGT_FLOWSET_PORT_Ym:
        mem = DLB_HGT_FLOWSET_PORTm;
        break;

        /* ip5_1 */
    case MODPORT_MAP_MIRRORm:
        mem = MODPORT_MAP_M0m;
        break;
    case ING_PW_TERM_SEQ_NUM_Xm:
    case ING_PW_TERM_SEQ_NUM_Ym:
        mem = ING_PW_TERM_SEQ_NUMm;
        break;
    case ING_SERVICE_COUNTER_TABLE_Xm:
    case ING_SERVICE_COUNTER_TABLE_Ym:
        mem = ING_SERVICE_COUNTER_TABLEm;
        break;
    case ING_VINTF_COUNTER_TABLE_Xm:
    case ING_VINTF_COUNTER_TABLE_Ym:
        mem = ING_VINTF_COUNTER_TABLEm;
        break;
    default:
        break;
    }

    /* Loop through each place-and-route block entry */
    for (route_block_index = 0; ; route_block_index++) {
        route_block = &_soc_trident_parity_route_blocks[route_block_index];
        cmic_bit = route_block->cmic_bit;
        if (cmic_bit == 0) {
            /* End of table */
            break;
        }

        if (route_block->blocktype == SOC_BLK_PORT_GROUP4 ||
            route_block->blocktype == SOC_BLK_PORT_GROUP5) {
            inst_num = route_block->pipe;
        } else {
            inst_num = 0;
        }
        SOC_BLOCK_ITER(unit, block_info_idx, route_block->blocktype) {
            if (SOC_BLOCK_INFO(unit, block_info_idx).number == inst_num) {
                break;
            }
        }

        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         &route_block_rval));

        rv = _soc_trident_parity_enable_info(unit, block_info_idx,
                                             route_block->pipe,
                                             route_block->enable_reg,
                                             &route_block_rval,
                                             route_block->info, mem, enable);

        if (rv != SOC_E_NOT_FOUND) {
            return rv;
        }

        /* Write per route block parity enable register */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         route_block_rval));
    }

    if (SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem)) == SOC_BLK_MMU) {
        /* MMU controls */
        if (enable) {
            SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_STAT_CLEARf, 1);
            SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
            
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_CHK_ENf, 1);
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_GEN_ENf, 1);
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_STAT_CLEARf, 0);
            soc_reg_field_set(unit, MISCCONFIGr, &rval, METERING_CLK_ENf, 1);
            SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
        } else {
            SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_CHK_ENf, 0);
            soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_GEN_ENf, 0);
            soc_reg_field_set(unit, MISCCONFIGr, &rval, METERING_CLK_ENf, 0);
            SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
        }
    }

    return SOC_E_NONE;
}

STATIC void
_soc_mem_parity_info(int unit, int block_info_idx, int pipe,
                     soc_field_t field_enum, uint32 *minfo)
{
    *minfo = (SOC_BLOCK_INFO(unit, block_info_idx).cmic << SOC_ERROR_BLK_BP)
        | ((pipe & 0xff) << SOC_ERROR_PIPE_BP)
        | (field_enum & SOC_ERROR_FIELD_ENUM_MASK);
}

STATIC int
_soc_trident_parity_process_info(int unit, int block_info_idx, int pipe,
                                 soc_reg_t reg, uint32 group_rval,
                                 const _soc_trident_parity_info_t *info_list,
                                 char *prefix_str);

STATIC int
_soc_trident_parity_process_parity(int unit, int block_info_idx, int pipe,
                                   const _soc_trident_parity_info_t *info,
                                   int schan, char *prefix_str, char *mem_str)
{
    _soc_trident_parity_reg_t reg_entry[2], *reg_ptr;
    soc_reg_t reg;
    uint32 rval, minfo;
    uint32 multiple, entry_idx, idx, has_error;
    char *mem_str_ptr;

    if (schan) {
        /* Some table does not have NACK register */
        if (info->nack_status_reg == INVALIDr &&
            info->nack_status_reg_list == NULL) {
            return SOC_E_NONE;
        }
        reg_entry[0].reg = info->nack_status_reg;
        reg_entry[0].mem_str = NULL;
        reg_entry[1].reg = INVALIDr;
        reg_ptr = reg_entry;
    } else {
        if (info->intr_status_reg != INVALIDr) {
            reg_entry[0].reg = info->intr_status_reg;
            reg_entry[0].mem_str = NULL;
            reg_entry[1].reg = INVALIDr;
            reg_ptr = reg_entry;
        } else if (info->intr_status_reg_list != NULL) {
            reg_ptr = info->intr_status_reg_list;
        } else {
            return SOC_E_NONE;
        }
    }

    has_error = FALSE;
    for (idx = 0; reg_ptr[idx].reg != INVALIDr; idx++) {
        reg = reg_ptr[idx].reg;
        mem_str_ptr = reg_ptr[idx].mem_str != NULL ?
            reg_ptr[idx].mem_str : mem_str;
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg,
                                         &rval));

        if (soc_reg_field_get(unit, reg, rval, PARITY_ERRf)) {
            has_error = TRUE;
            multiple = soc_reg_field_get(unit, reg, rval, MULTIPLE_ERRf);
            entry_idx = soc_reg_field_get(unit, reg, rval, ENTRY_IDXf);
            _soc_mem_parity_info(unit, block_info_idx, pipe,
                                 info->group_reg_status_field, &minfo);
            soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                               SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 
                               entry_idx, minfo);
            soc_cm_debug(DK_ERR,
                         "%s %s entry %d parity error\n",
                         prefix_str, mem_str_ptr, entry_idx);
            if (multiple) {
                soc_cm_debug(DK_ERR,
                             "%s %s has multiple parity errors\n",
                             prefix_str, mem_str_ptr);
            }
        }

        /* Clear parity status */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg, 0));
    }

    if (!has_error) {
        soc_cm_debug(DK_ERR,
                     "%s %s parity hardware inconsistency\n",
                     prefix_str, mem_str);
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_ecc(int unit, int block_info_idx, int pipe,
                                const _soc_trident_parity_info_t *info,
                                int schan, char *prefix_str, char *mem_str)
{
    _soc_trident_parity_reg_t reg_entry[2], *reg_ptr;
    soc_reg_t reg;
    uint32 rval, minfo;
    uint32 multiple, double_bit, entry_idx, idx, has_error;
    char *mem_str_ptr;

    if (schan) {
        /* Some table does not have NACK register */
        if (info->nack_status_reg == INVALIDr &&
            info->nack_status_reg_list == NULL) {
            return SOC_E_NONE;
        }
        reg_entry[0].reg = info->nack_status_reg;
        reg_entry[0].mem_str = NULL;
        reg_entry[1].reg = INVALIDr;
        reg_ptr = reg_entry;
    } else {
        if (info->intr_status_reg != INVALIDr) {
            reg_entry[0].reg = info->intr_status_reg;
            reg_entry[0].mem_str = NULL;
            reg_entry[1].reg = INVALIDr;
            reg_ptr = reg_entry;
        } else if (info->intr_status_reg_list != NULL) {
            reg_ptr = info->intr_status_reg_list;
        } else {
            return SOC_E_NONE;
        }
    }

    has_error = FALSE;
    for (idx = 0; reg_ptr[idx].reg != INVALIDr; idx++) {
        reg = reg_ptr[idx].reg;
        mem_str_ptr = reg_ptr[idx].mem_str != NULL ?
            reg_ptr[idx].mem_str : mem_str;
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg,
                                         &rval));

        if (soc_reg_field_get(unit, reg, rval, ECC_ERRf)) {
            has_error = TRUE;
            multiple = soc_reg_field_get(unit, reg, rval, MULTIPLE_ERRf);
            double_bit = soc_reg_field_get(unit, reg, rval, DOUBLE_BIT_ERRf);
            entry_idx = soc_reg_field_get(unit, reg, rval, ENTRY_IDXf);
            _soc_mem_parity_info(unit, block_info_idx, pipe,
                                 info->group_reg_status_field, &minfo);
            soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                               SOC_SWITCH_EVENT_DATA_ERROR_ECC, 
                               entry_idx, minfo);
            if (double_bit) {
                soc_cm_debug(DK_ERR,
                             "%s %s entry %d double-bit ECC error\n",
                             prefix_str, mem_str_ptr, entry_idx);
            } else {
                soc_cm_debug(DK_ERR,
                             "%s %s entry %d ECC error\n",
                             prefix_str, mem_str_ptr, entry_idx);
            }
            if (multiple) {
                soc_cm_debug(DK_ERR,
                             "%s %s has multiple ECC errors\n",
                             prefix_str, mem_str_ptr);
            }
        }

        /* Clear parity status */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg, 0));
    }

    if (!has_error) {
        soc_cm_debug(DK_ERR,
                     "%s %s ECC hardware inconsistency\n",
                     prefix_str, mem_str);
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_hash(int unit, int block_info_idx, int pipe,
                                 const _soc_trident_parity_info_t *info,
                                 int schan, char *prefix_str, char *mem_str)
{
    _soc_trident_parity_reg_t *reg_ptr;
    soc_reg_t reg;
    uint32 rval, minfo;
    uint32 bitmap, multiple, bucket_idx;
    int bucket_size, entry_idx, idx, bits, has_error;

    if (schan) {
        reg_ptr = info->nack_status_reg_list;
    } else {
        reg_ptr = info->intr_status_reg_list;
    }

    has_error = FALSE;
    for (idx = 0; idx < 2; idx ++) {
        reg = reg_ptr[idx].reg;
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg,
                                         &rval));

        bitmap = soc_reg_field_get(unit, reg, rval, PARITY_ERR_BMf);
        if (bitmap != 0) {
            has_error = TRUE;
            multiple = soc_reg_field_get(unit, reg, rval, MULTIPLE_ERRf);
            bucket_idx = soc_reg_field_get(unit, reg, rval, BUCKET_IDXf);
            bucket_size = soc_reg_field_length(unit, reg, PARITY_ERR_BMf);
            for (bits = 0; bits < bucket_size; bits++) {
                if (bitmap & (1 << bits)) {
                    entry_idx = (bucket_idx * 2 + idx) * bucket_size + bits;
                    _soc_mem_parity_info(unit, block_info_idx, pipe,
                                         info->group_reg_status_field, &minfo);
                    soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                                       SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 
                                       entry_idx, minfo);
                    soc_cm_debug(DK_ERR,
                                 "%s %s entry %d parity error\n",
                                 prefix_str, mem_str, entry_idx);
                }
            }
            if (multiple) {
                soc_cm_debug(DK_ERR,
                             "%s %s has multiple parity errors\n",
                             prefix_str, mem_str);
            }
        }

        /* Clear parity status */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg, 0));
    }

    if (!has_error) {
        soc_cm_debug(DK_ERR,
                     "%s %s parity hardware inconsistency\n",
                     prefix_str, mem_str);
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_edatabuf(int unit, int block_info_idx, int pipe,
                                     const _soc_trident_parity_info_t *info,
                                     int schan, char *prefix_str,
                                     char *mem_str)
{
    soc_reg_t reg;
    uint32 rval, minfo;
    uint32 double_bit, multiple;

    if (schan) {
        /* Some table may not have NACK status register */
        if (info->nack_status_reg == INVALIDr) {
            return SOC_E_NONE;
        }
        reg = info->nack_status_reg;
    } else {
        reg = info->intr_status_reg;
    }
    reg = schan ? info->nack_status_reg : info->intr_status_reg;
    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg, &rval));

    if (soc_reg_field_get(unit, reg, rval, ECC_ERR_MGRPf)) {
        double_bit = soc_reg_field_get(unit, reg, rval, ECC_ERR_2B_MGRPf);
        multiple = soc_reg_field_get(unit, reg, rval, ECC_MULTI_MGRPf);
        _soc_mem_parity_info(unit, block_info_idx, pipe,
                             info->group_reg_status_field, &minfo);
        soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                           SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 0, 
                           minfo);
        if (double_bit) {
            soc_cm_debug(DK_ERR,
                         "%s %s double-bit ECC error\n",
                         prefix_str, mem_str);
        } else {
            soc_cm_debug(DK_ERR,
                         "%s %s ECC error\n",
                         prefix_str, mem_str);
        }
        if (multiple) {
            soc_cm_debug(DK_ERR,
                         "%s %s has multiple ECC errors\n",
                         prefix_str, mem_str);
        }
    } else {
        soc_cm_debug(DK_ERR,
                     "%s %s ECC hardware inconsistency\n",
                     prefix_str, mem_str);
    }

    /* Clear parity status */
    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg, 0));

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_counter(int unit, int block_info_idx, int pipe,
                                    const _soc_trident_parity_info_t *info,
                                    int schan, char *prefix_str, char *mem_str)
{
    soc_cmap_t *cmap;
    soc_reg_t reg, counter_reg;
    uint32 rval, minfo;
    uint32 multiple, counter_idx, port_idx, entry_idx;
    char *counter_name;

    if (schan) {
        reg = info->nack_status_reg;
    } else {
        reg = info->intr_status_reg;
    }
    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_reg_get(unit, block_info_idx, pipe, reg, &rval));

    if (soc_reg_field_get(unit, reg, rval, PARITY_ERRf)) {
        multiple = soc_reg_field_get(unit, reg, rval, MULTIPLE_ERRf);
        counter_idx = soc_reg_field_get(unit, reg, rval, COUNTER_IDXf);
        port_idx = soc_reg_field_get(unit, reg, rval, PORT_IDXf);
        entry_idx = soc_reg_field_get(unit, reg, rval, ENTRY_IDXf);

        /* TDBGC starts at index 0x20 of counter DMA table */
        if (info->group_reg_status_field == EGR_STATS_COUNTER_TABLE_PAR_ERRf) {
            counter_idx += 0x20;
        }
        cmap = soc_port_cmap_get(unit, port_idx);
        counter_reg = cmap->cmap_base[counter_idx].reg;
        if (SOC_REG_IS_VALID(unit, counter_reg)) {
            _soc_mem_parity_info(unit, block_info_idx, pipe,
                                 info->group_reg_status_field, &minfo);
            soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                               SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 
                               entry_idx, minfo);
            counter_name = SOC_REG_NAME(unit, counter_reg);
            soc_cm_debug(DK_ERR,
                         "%s %s port %d %s entry %d parity error\n",
                         prefix_str, mem_str, port_idx, counter_name,
                         entry_idx);
            if (multiple) {
                soc_cm_debug(DK_ERR,
                             "%s %s has multiple parity errors\n",
                             prefix_str, mem_str);
            }
        } else {
            soc_cm_debug(DK_ERR,
                         "%s %s parity hardware inconsistency\n",
                         prefix_str, mem_str);
        }
    } else {
        soc_cm_debug(DK_ERR,
                     "%s %s parity hardware inconsistency\n",
                     prefix_str, mem_str);
    }

    /* Clear parity status */
    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_reg_set(unit, block_info_idx, pipe, reg, 0));

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_mmu_thdo(int unit, int block_info_idx,
                                     const _soc_trident_parity_info_t *info,
                                     char *prefix_str)
{
    uint64 rval64;
    uint32 entry_idx, rval_hi, rval_lo, minfo;
    int i;
    static const _soc_trident_parity_mmu_bit_t thdo[] = {
        /* { 0, MMU_THDO_QREDRST_EX_1m }, */
        /* { 1, MMU_THDO_QYELRST_EX_1m }, */
        /* { 4, MMU_THDO_QDRPRST_EX_1m }, */
        { 6, THDO_OFFSET_EX_1Bm },
        { 7, THDO_OFFSET_EX_1Am },
        { 8, THDO_CONFIG_EX_1Bm },
        { 9, THDO_CONFIG_EX_1Am },
        /* { 14, MMU_THDO_QREDRST_EX_0m }, */
        /* { 15, MMU_THDO_QYELRST_EX_0m }, */
        /* { 18, MMU_THDO_QDRPRST_EX_0m }, */
        { 20, THDO_OFFSET_EX_0Bm },
        { 21, THDO_OFFSET_EX_0Am },
        { 22, THDO_CONFIG_EX_0Bm },
        { 23, THDO_CONFIG_EX_0Am },
        /* { 28, MMU_THDO_QREDRST_1m }, */
        /* { 29, MMU_THDO_QYELRST_1m }, */
        /* { 30, MMU_THDO_QDRPRST_1m }, */
        { 31, THDO_OFFSET_1Bm },
        { 32, THDO_OFFSET_1Am },
        { 33, THDO_CONFIG_1Bm },
        { 34, THDO_CONFIG_1Am },
        /* { 35, MMU_THDO_QREDRST_0m }, */
        /* { 36, MMU_THDO_QYELRST_0m }, */
        /* { 37, MMU_THDO_QDRPRST_0m }, */
        { 38, THDO_OFFSET_0Bm },
        { 39, THDO_OFFSET_0Am },
        { 40, THDO_CONFIG_0Bm },
        { 41, THDO_CONFIG_0Am }
    };

    SOC_IF_ERROR_RETURN(READ_THDO_PARITY_ERROR_STATUS_64r(unit, &rval64));
    rval_hi = COMPILER_64_HI(rval64);
    rval_lo = COMPILER_64_LO(rval64);

    SOC_IF_ERROR_RETURN(READ_THDO_PARITY_ERROR_ADDRESSr(unit, &entry_idx));

    for (i = 0; i < sizeof(thdo) / sizeof(thdo[0]); i++) {
        if (thdo[i].bit_pos < 32) {
            if (!(rval_lo & (1 << thdo[i].bit_pos))) {
                continue;
            }
        } else {
            if (!(rval_hi & (1 << (thdo[i].bit_pos - 32)))) {
                continue;
            }
        }

        _soc_mem_parity_info(unit, block_info_idx, 0,
                             info->group_reg_status_field, &minfo);
        soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                           SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 0,
                           minfo);
        soc_cm_debug(DK_ERR, "%s %s entry %d parity error\n", prefix_str,
                     SOC_MEM_NAME(unit, thdo[i].mem), entry_idx);
    }

    /* Clear parity status */
    COMPILER_64_ZERO(rval64);
    SOC_IF_ERROR_RETURN(WRITE_THDO_PARITY_ERROR_STATUS_64r(unit, rval64));

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_xlport(int unit, int pipe,
                                   const _soc_trident_parity_info_t *info)
{
    soc_reg_t xlport_reg;
    uint32 xlport_rval;
    int block_info_idx, inst_num, port;
    char prefix_str[24];

    if (info->intr_status_reg == INVALIDr) {
        return SOC_E_NONE;
    }

    port = -1;
    inst_num = info->id + pipe * 9;
    SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
        if (SOC_BLOCK_INFO(unit, block_info_idx).number == inst_num) {
            port = SOC_BLOCK_PORT(unit, block_info_idx);
            break;
        }
    }
    if (port < 0) {
        return SOC_E_NONE;
    }

    xlport_reg = info->intr_status_reg;
    SOC_IF_ERROR_RETURN
        (soc_reg32_get(unit, xlport_reg, port, 0, &xlport_rval));
    if (xlport_rval == 0) {
        return SOC_E_NONE;
    }

    sal_sprintf(prefix_str, "unit %d XLPORT%d", unit, inst_num);
    SOC_IF_ERROR_RETURN
        (_soc_trident_parity_process_info(unit, block_info_idx, pipe,
                                          xlport_reg, xlport_rval,
                                          info->info, prefix_str));

    return SOC_E_NONE;
}

STATIC int
_soc_trident_parity_process_info(int unit, int block_info_idx, int pipe,
                                 soc_reg_t group_reg, uint32 group_rval,
                                 const _soc_trident_parity_info_t *info_list,
                                 char *prefix_str)
{
    const _soc_trident_parity_info_t *info;
    int info_index;
    char *mem_str;
    uint32 minfo;

    /* Loop through each info entry in the list */
    for (info_index = 0; ; info_index++) {
        info = &info_list[info_index];
        if (info->type == _SOC_PARITY_TYPE_NONE) {
            /* End of table */
            break;
        }

        /* Check status for the info entry in the group register */
        if (!soc_reg_field_get(unit, group_reg, group_rval,
                               info->group_reg_status_field)) {
            continue;
        }

        if (info->mem_str) {
            mem_str = info->mem_str;
        } else if (info->mem != INVALIDm) {
            mem_str = SOC_MEM_NAME(unit, info->mem);
        } else {
            mem_str = SOC_FIELD_NAME(unit, info->group_reg_status_field);
        }

        /* Handle different parity error reporting style */
        switch (info->type) {
        case _SOC_PARITY_TYPE_GENERIC:
            _soc_mem_parity_info(unit, block_info_idx, pipe,
                                 info->group_reg_status_field, &minfo);
            soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 
                               SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 0,
                               minfo);
            soc_cm_debug(DK_ERR, "%s %s asserted\n", prefix_str, mem_str);
            break;
        case _SOC_PARITY_TYPE_PARITY:
            /* PARITY_ERRf, MULTIPLE_ERRf, ENTRY_IDXf */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_parity(unit, block_info_idx,
                                                    pipe, info, FALSE,
                                                    prefix_str, mem_str));
            break;
        case _SOC_PARITY_TYPE_ECC:
            /* ECC_ERRf, MULTIPLE_ERRf, DOUBLE_BIT_ERRf, ENTRY_IDXf */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_ecc(unit, block_info_idx, pipe,
                                                 info, FALSE,
                                                 prefix_str, mem_str));
            break;
        case _SOC_PARITY_TYPE_HASH:
            /* PARITY_ERR_BMf, MULTIPLE_ERRf, BUCKET_IDXf */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_hash(unit, block_info_idx,
                                                  pipe, info, FALSE,
                                                  prefix_str, mem_str));
            break;
        case _SOC_PARITY_TYPE_EDATABUF:
            /* ECC_ERR_MGRPf, ECC_ERR_2B_MGRPf, ECC_MULTI_MGRPf */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_edatabuf(unit, block_info_idx,
                                                      pipe, info, FALSE,
                                                      prefix_str, mem_str));
            break;
        case _SOC_PARITY_TYPE_COUNTER:
            /* PARITY_ERRf, MULTIPLE_ERRf, COUNTER_IDXf, PORT_IDX,
               ENTRY_IDXf */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_counter(unit, block_info_idx,
                                                     pipe, info, FALSE,
                                                     prefix_str, mem_str));
            break;
        case _SOC_PARITY_TYPE_XLPORT:
            /* One more level of report tree structure */
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_xlport(unit, pipe, info));
            break;
        case _SOC_PARITY_TYPE_MMU_THDO:
            SOC_IF_ERROR_RETURN
                (_soc_trident_parity_process_mmu_thdo(unit, block_info_idx,
                                                      info, prefix_str));
            break;
        default:
            break;
        } /* Handle different parity error reporting style */
    } /* Loop through each info entry in the list */

    return SOC_E_NONE;
}

#if 0
/* 
 * This code can be used to spit out a C struct database of all
 * reportable memory errors and their associated arg3 values.
 *
 * This database can be used to maintain statistics on reported memory
 * errors on a per-memory basis (versus globally).
 * 
 * To generate a new database, set #if 1 above, and run this code
 * from a diagnostic shell command.
 *
 * This code must remain in this file because the error reporting
 * information used to generate arg3 values is local to this file.
 *
 */
void
soc_trident_print_memories(int unit)
{
    const _soc_trident_parity_route_block_t *rb;
    _soc_trident_parity_info_t *mi, *mi0;
    char prefix[64];
    char *mn;
    uint32 id;
    int ecc, blk_num, blk;

    for (rb = _soc_trident_parity_route_blocks; rb->cmic_bit; rb++) {
        for (mi = rb->info; mi->type != _SOC_PARITY_TYPE_NONE; mi++) {
            if (mi->type != _SOC_PARITY_TYPE_GENERIC
                && mi->intr_status_reg == INVALIDr
                && !mi->intr_status_reg_list) {
                continue;
            }
            if (mi->type == _SOC_PARITY_TYPE_XLPORT) {
                mi0 = mi->info;
            } else {
                mi0 = mi;
            }
            
            if (mi0->mem_str) {
                mn = mi0->mem_str;
            } else if (mi0->mem != INVALIDm) {
                mn = SOC_MEM_NAME(unit, mi0->mem);
            } else {
                mn = SOC_FIELD_NAME(unit, mi0->group_reg_status_field);
            }
            
            blk = rb->blocktype;
            if (mi->type == _SOC_PARITY_TYPE_XLPORT) {
                blk_num = mi->id + rb->pipe * 9;
                SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
                    if (SOC_BLOCK_INFO(unit, blk).number == blk_num) break;
                }
                sal_sprintf(prefix, "%s,XLPORT%d", mn, blk_num);
                _soc_mem_parity_info(unit, blk, rb->pipe, 
                                     mi0->group_reg_status_field, &id);
            } else {
                if (rb->pipe >= 0) {
                    sal_sprintf(prefix, "%s,%d", mn, rb->pipe);
                } else {
                    sal_sprintf(prefix, "%s", mn);
                }
                _soc_mem_parity_info(unit, rb->blocktype, rb->pipe, 
                                     mi0->group_reg_status_field, &id);
            }
            ecc = mi0->type == _SOC_PARITY_TYPE_ECC;
            soc_cm_print("      {\"%s\", %d, 0x%08x},\n", prefix, ecc, id);
        }
    }
}
#endif

STATIC int
_soc_trident_parity_process_all(int unit)
{
    const _soc_trident_parity_route_block_t *route_block;
    int route_block_index;
    uint32 cmic_rval, route_block_rval;
    uint32 route_block_enable;
    uint32 cmic_bit;
    int block_info_idx, inst_num;
    char prefix_str[10];

    sal_sprintf(prefix_str, "unit %d", unit);

    /* Read CMIC parity status register */
    SOC_IF_ERROR_RETURN
        (READ_CMIC_CHIP_PARITY_INTR_STATUSr(unit, &cmic_rval));
    if (cmic_rval == 0) {
        return SOC_E_NONE;
    }

    /* Loop through each place-and-route block entry */
    for (route_block_index = 0; ; route_block_index++) {
        route_block = &_soc_trident_parity_route_blocks[route_block_index];
        cmic_bit = route_block->cmic_bit;
        if (cmic_bit == 0) {
            /* End of table */
            break;
        }

        /* Check status for the route block in the CMIC register */
        if (!(cmic_rval & cmic_bit)) {
            /* No interrupt bit asserted for the route block */
            continue;
        }

        if (route_block->blocktype == SOC_BLK_PORT_GROUP4 ||
            route_block->blocktype == SOC_BLK_PORT_GROUP5) {
            inst_num = route_block->pipe;
        } else {
            inst_num = 0;
        }
        SOC_BLOCK_ITER(unit, block_info_idx, route_block->blocktype) {
            if (SOC_BLOCK_INFO(unit, block_info_idx).number == inst_num) {
                break;
            }
        }

        /* Read per route block parity status register */
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->status_reg,
                                         &route_block_rval));
        if (route_block_rval == 0) {
            continue;
        }

        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_process_info(unit, block_info_idx,
                                              route_block->pipe,
                                              route_block->status_reg,
                                              route_block_rval,
                                              route_block->info,
                                              prefix_str));

        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_get(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         &route_block_enable));
        route_block_enable &= ~route_block_rval;
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         route_block_enable));
        route_block_enable |= route_block_rval;
        SOC_IF_ERROR_RETURN
            (_soc_trident_parity_reg_set(unit, block_info_idx,
                                         route_block->pipe,
                                         route_block->enable_reg,
                                         route_block_enable));
    } /* Loop through each place-and-route block entry */

    return SOC_E_NONE;
}

void
soc_trident_parity_error(void *unit_vp, void *d1, void *d2, void *d3, void *d4)
{
    int unit = PTR_TO_INT(unit_vp);

    _soc_trident_parity_process_all(unit);
    sal_usleep(1000); /* Don't reenable too soon */
    soc_intr_enable(unit, IRQ_MEM_FAIL);
}

/* SER processing for TCAMs */
STATIC _soc_ser_parity_info_t _soc_td_ser_parity_info[] = {
    { EFP_TCAMm, _SOC_SER_PARITY_MODE_2BITS,
      CMIC_SER_START_ADDR_0r, CMIC_SER_END_ADDR_0r,
      CMIC_SER_MEM_ADDR_0r, RANGE_0_PARITY_BITSf, 0, 0},
    { FP_TCAMm, _SOC_SER_PARITY_MODE_2BITS,
      CMIC_SER_START_ADDR_1r, CMIC_SER_END_ADDR_1r,
      CMIC_SER_MEM_ADDR_1r, RANGE_1_PARITY_BITSf, 0, 0},
    { VFP_TCAMm, _SOC_SER_PARITY_MODE_2BITS,
      CMIC_SER_START_ADDR_2r, CMIC_SER_END_ADDR_2r,
      CMIC_SER_MEM_ADDR_2r, RANGE_2_PARITY_BITSf, 0, 0},
    { FP_UDF_TCAMm, _SOC_SER_PARITY_MODE_2BITS,
      CMIC_SER_START_ADDR_3r, CMIC_SER_END_ADDR_3r,
      CMIC_SER_MEM_ADDR_3r, RANGE_3_PARITY_BITSf, 0, 0},
    
    { INVALIDm, _SOC_SER_PARITY_MODE_NUM},
};

#define SOC_TD_SER_MEM_AVAILABLE       (2048 * 32)  /* bits */

STATIC int
_soc_trident_ser_init(int unit)
{
    return soc_ser_init(unit, _soc_td_ser_parity_info,
                        SOC_TD_SER_MEM_AVAILABLE);
}

int
soc_trident_ser_mem_clear(int unit, soc_mem_t mem)
{
    return soc_ser_mem_clear(unit, _soc_td_ser_parity_info, mem);
}

void
soc_trident_ser_fail(int unit)

{
    soc_process_ser_parity_error(unit, _soc_td_ser_parity_info,
                                 _SOC_PARITY_TYPE_SER);
    return;
}

STATIC int
_soc_trident_clear_all_memory(int unit)
{
    soc_info_t          *si;
    uint32              rval, fval;
    int                 pipe_init_usec, index, count;
    soc_timeout_t       to;
    uint32              entry[SOC_MAX_MEM_WORDS];
    int                 port, phy_port, blk_port, blk, bindex;
    static const soc_mem_t cam[] = {
        CPU_COS_MAP_ONLYm,
        FP_GLOBAL_MASK_TCAMm,
        FP_GM_FIELDSm,
        FP_TCAMm,
        FP_UDF_TCAMm,
        L2_USER_ENTRY_ONLYm,
        L3_DEFIP_128_ONLYm,
        L3_DEFIP_ONLYm,
        L3_TUNNELm,
        MY_STATION_TCAM_ENTRY_ONLYm,
        VFP_TCAMm,
        VLAN_SUBNET_ONLYm,
        EFP_TCAMm,
#ifdef PLISIM
        FP_GLOBAL_MASK_TCAM_Xm,
        FP_GLOBAL_MASK_TCAM_Ym
#endif
    };

    si = &SOC_INFO(unit);

    /*
     * Reset the IPIPE and EPIPE block
     */
    rval = 0;
    SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval));
    soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
    soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
    /* Set count to # entries in largest IPIPE table (L2X) */
    count = soc_mem_index_count(unit, L2Xm);
    soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, count);
    SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));

    rval = 0;
    SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval));
    soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
    soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
    /* Set count to # entries in largest EPIPE table (EGR_L3_NEXT_HOP) */
    count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
    SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));

    /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
    if (SAL_BOOT_SIMULATION) {
        pipe_init_usec = 10000000;
    } else {
        pipe_init_usec = 50000;
    }
    soc_timeout_init(&to, pipe_init_usec, 0);

    /* Wait for IPIPE memory initialization done. */
    do {
        SOC_IF_ERROR_RETURN(READ_ING_HW_RESET_CONTROL_2r(unit, &rval));
        if (soc_reg_field_get(unit, ING_HW_RESET_CONTROL_2r, rval, DONEf)) {
            break;
        }
        if (soc_timeout_check(&to)) {
            soc_cm_debug(DK_WARN, "unit %d : ING_HW_RESET timeout\n", unit);
            break;
        }
    } while (TRUE);

    /* Wait for EPIPE memory initialization done. */
    do {
        SOC_IF_ERROR_RETURN(READ_EGR_HW_RESET_CONTROL_1r(unit, &rval));
        if (soc_reg_field_get(unit, EGR_HW_RESET_CONTROL_1r, rval, DONEf)) {
            break;
        }
        if (soc_timeout_check(&to)) {
            soc_cm_debug(DK_WARN, "unit %d : EGR_HW_RESET timeout\n", unit);
            break;
        }
    } while (TRUE);

    rval = 0;
    SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
    SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));

    /* TCAM tables are not handled by hardware reset control */
    for (index = 0; index < sizeof(cam) / sizeof(soc_mem_t); index++) {
        SOC_IF_ERROR_RETURN(soc_mem_clear(unit, cam[index], COPYNO_ALL, TRUE));
    }

    /* Do dummy read to clear the parity status latch */
    SOC_IF_ERROR_RETURN
        (READ_INITIAL_L3_ECMP_Xm(unit, MEM_BLOCK_ANY, 0, entry));
    SOC_IF_ERROR_RETURN
        (READ_INITIAL_L3_ECMP_Ym(unit, MEM_BLOCK_ANY, 0, entry));

    /* Some registers are implemented in memory, need to clear them in order
     * to have correct parity value */
    PBMP_ALL_ITER(unit, port) {
        SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, 0));
        SOC_IF_ERROR_RETURN(WRITE_EGR_IPMC_CFG2r(unit, port, 0));
    }

    /* Reset XLPORT MIB counter (registers implemented in memory). The clear
     * function is implemented with read-modify-write, parity needs to be
     * disabled */
    SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
        blk_port = SOC_BLOCK_PORT(unit, blk);
        if (blk_port < 0) {
            continue;
        }
        phy_port = ((si->port_l2p_mapping[blk_port] - 1) & ~0x3) + 1;
        fval = 0;
        for (bindex = 0; bindex < 4; bindex++) {
            if (si->port_p2l_mapping[phy_port + bindex] != -1) {
                fval |= 1 << bindex;
            }
        }
        rval = 0;
        soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, fval);
        SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, blk_port, rval));
        SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, blk_port, 0));
    }

    return SOC_E_NONE;
}

int
soc_trident_pipe_select(int unit, int egress, int pipe)
{
    soc_reg_t reg;

    reg = egress ? EGR_SBS_CONTROLr : SBS_CONTROLr;
    return soc_reg_field32_modify(unit, reg, REG_PORT_ANY, PIPE_SELECTf, pipe);
}

int
_soc_trident_port_mapping_init(int unit)
{
    soc_info_t *si;
    soc_mem_t mem;
    uint32 rval;
    ing_physical_to_logical_port_number_mapping_table_entry_t entry;
    int port, phy_port, mmu_port;
    int num_port, num_phy_port, num_mmu_port;

    si = &SOC_INFO(unit);

    /* Ingress physical to logical port mapping */
    mem = ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm;
    num_phy_port = soc_mem_index_count(unit, mem);
    sal_memset(&entry, 0, sizeof(entry));
    for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
        port = si->port_p2l_mapping[phy_port];
        soc_mem_field32_set(unit, mem, &entry, LOGICAL_PORT_NUMBERf,
                            port == -1 ? 0x7f : port);
        SOC_IF_ERROR_RETURN
            (soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port, &entry));
    }

    /* Ingress logical to physical port mapping */
    num_port = soc_mem_index_count(unit, PORT_TABm);
    rval = 0;
    for (port = 0; port < num_port; port++) {
        phy_port = si->port_l2p_mapping[port];
        soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval,
                          PHYSICAL_PORT_NUMf,
                          phy_port == -1 ? 0x7f : phy_port);
        SOC_IF_ERROR_RETURN
            (WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval));
    }

    /* Egress logical to physical port mapping */
    for (port = 0; port < num_port; port++) {
        phy_port = si->port_l2p_mapping[port];
        rval = 0;
        soc_reg_field_set(unit, EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr,
                          &rval, PHYSICAL_PORT_NUMBERf,
                          phy_port == -1 ? 0x7f : phy_port);
        SOC_IF_ERROR_RETURN
            (WRITE_EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr(unit, port,
                                                                rval));

        rval = 0;
        soc_reg_field_set(unit, EGR_VLAN_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval,
                          PHYSICAL_PORT_NUMf,
                          phy_port == -1 ? 0x7f : phy_port);
        SOC_IF_ERROR_RETURN
            (WRITE_EGR_VLAN_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval));
    }

    /* MMU to physical port mapping and MMU to logical port mapping */
    num_mmu_port = SOC_REG_NUMELS(unit, MMU_TO_PHY_PORT_MAPPINGr);
    for (mmu_port = 0; mmu_port < num_mmu_port; mmu_port++) {
        phy_port = si->port_m2p_mapping[mmu_port];
        port = phy_port == -1 ? -1 : si->port_p2l_mapping[phy_port];

        rval = 0;
        soc_reg_field_set(unit, MMU_TO_PHY_PORT_MAPPINGr, &rval, PHY_PORTf,
                          phy_port == -1 ? 0x7f : phy_port);
        SOC_IF_ERROR_RETURN
            (WRITE_MMU_TO_PHY_PORT_MAPPINGr(unit, mmu_port, rval));

        rval = 0;
        soc_reg_field_set(unit, MMU_TO_LOGIC_PORT_MAPPINGr, &rval, LOGIC_PORTf,
                          port == -1 ? 0x7f : port);
        SOC_IF_ERROR_RETURN
            (WRITE_MMU_TO_LOGIC_PORT_MAPPINGr(unit, mmu_port, rval));
    }

    return SOC_E_NONE;
}

/*
 * cpu port (mmu port 0): 48 queues (0-47)
 * loopback port (mmu port 33): 9 queues (0-8)
 * extended ports (mmu port 1-4, 34-37): 74 unicast queues (0-9, 64-127)
 *                                       5 multicast queues (0-4)
 * regular port: 10 unicast queues (0-9)
 *               5 multicast queues (0-4)
 */
int
soc_trident_num_cosq_init(int unit)
{
    soc_info_t *si;
    int port, phy_port, mmu_port, mmu_cmic_port, mmu_lb_port;

    si = &SOC_INFO(unit);

    mmu_cmic_port = si->port_p2m_mapping[si->port_l2p_mapping[si->cmic_port]];
    mmu_lb_port = si->port_p2m_mapping[si->port_l2p_mapping[si->lb_port]];

    PBMP_ALL_ITER(unit, port) {
        phy_port = si->port_l2p_mapping[port];
        mmu_port = si->port_p2m_mapping[phy_port];

        si->port_num_cosq[port] = 5;
        si->port_num_uc_cosq[port] = 10;
        si->port_num_ext_cosq[port] = 0;
        if (phy_port <= 36) { /* X pipe */
            if (mmu_port == mmu_cmic_port) {
                si->port_num_cosq[port] = 48;
                si->port_num_uc_cosq[port] = 0;
                si->port_group[port] = -1;
            } else {
                if (mmu_port <= mmu_cmic_port + 4) {
                    si->port_num_ext_cosq[port] = 64;
                }
                if (phy_port <= 20) {
                    si->port_group[port] = 0; /* PORT_GROUP5_X */
                } else {
                    si->port_group[port] = 1; /* PORT_GROUP4_X */
                }
            }
        } else { /* Y pipe */
            if (mmu_port == mmu_lb_port) {
                si->port_num_cosq[port] = 9;
                si->port_num_uc_cosq[port] = 0;
                si->port_group[port] = -1;
            } else {
                if (mmu_port <= mmu_lb_port + 4) {
                    si->port_num_ext_cosq[port] = 64;
                }
                if (phy_port <= 56) {
                    si->port_group[port] = 2; /* PORT_GROUP5_Y */
                } else {
                    si->port_group[port] = 3; /* PORT_GROUP4_Y */
                }
            }
        }
    }

    return SOC_E_NONE;
}

/*
 * EGR_PERQ_XMT_COUNTERS_BASE_ADDR is indexed by:
 * port number[6:0], queue number[6], mcast(1)/ucast(0)
 *
 * EGR_PERQ_XMT_COUNTERS_X: can hold up to 784 counters
 *                          (cpu + 28 regular + 4 extended)
 * EGR_PERQ_XMT_COUNTERS_Y: can hold up to 745 counters
 *                          (loopback + 28 regular + 4 extended)
 */
int
soc_trident_get_egr_perq_xmt_counters_size(int unit, int *num_entries_x,
                                           int *num_entries_y)
{
    soc_info_t *si;
    soc_port_t port;

    si = &SOC_INFO(unit);

    *num_entries_x = *num_entries_y = 0;
    PBMP_ALL_ITER(unit, port) {
        if (IS_CPU_PORT(unit, port) ||
            (si->port_group[port] >= 0 && si->port_group[port] <= 1)) {
            *num_entries_x += si->port_num_cosq[port] +
                si->port_num_uc_cosq[port] + si->port_num_ext_cosq[port];
        } else {
            *num_entries_y += si->port_num_cosq[port] +
                si->port_num_uc_cosq[port] + si->port_num_ext_cosq[port];
        }
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_egr_perq_xmt_counters_init(int unit)
{
    soc_info_t *si;
    soc_port_t port;
    int base_x, base_y, *base;
    int num_entries[3], idx;
    egr_perq_xmt_counters_base_addr_entry_t entry;

    si = &SOC_INFO(unit);

    base_x = base_y = 0;
    sal_memset(&entry, 0, sizeof(entry));

    PBMP_ALL_ITER(unit, port) {
        if (IS_CPU_PORT(unit, port) ||
            (si->port_group[port] >= 0 && si->port_group[port] <= 1)) {
            base = &base_x;
        } else {
            base = &base_y;
        }
        num_entries[0] = si->port_num_uc_cosq[port];
        num_entries[1] = si->port_num_cosq[port];
        num_entries[2] = si->port_num_ext_cosq[port];

        for (idx = 0; idx < 3; idx++) {
            if (!num_entries[idx]) {
                continue;
            }
            soc_mem_field32_set(unit, EGR_PERQ_XMT_COUNTERS_BASE_ADDRm, &entry,
                                BASEf, *base);
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, EGR_PERQ_XMT_COUNTERS_BASE_ADDRm,
                               MEM_BLOCK_ALL, (port << 2) + idx, &entry));
            (*base) += num_entries[idx];
        }
    }

    return SOC_E_NONE;
}


#define _TD_BLKS_PER_PIPE    9
#define _TD_BLKS_PER_GROUP   5 /* can be 4 or 5 */
#define _TD_PORTS_PER_BLK    4
#define _TD_TDM_SLOT_IDLE   -1
#define _TD_TDM_SLOT_NULL   -2
#define _TD_TDM_NUM_COLUMNS 4
#define _TD_TDM_NUM_SLOTS   8

/*
 * Trident port mapping
 *     74 physical ports: port 0-36 in X pipe, port 37-73 in Y pipe
 *     66 logical ports
 *     66 mmu ports: port 0-32 in X pipe, port 33-65 in Y pipe
 *     cpu port number is fixed: physical 0, logical 0, mmu 0
 *     loopback port number is fixed: physical 73, logical 65, mmu 33
 *     physical port 1-4 can be converted to GE port
 *     mmu port can only map to physical port ID in the same pipe
 * This routine will setup:
 *     SOC_INFO(unit).port_p2l_mapping[]
 *     SOC_INFO(unit).port_l2p_mapping[]
 *     SOC_INFO(unit).port_p2m_mapping[]
 *     SOC_INFO(unit).port_m2p_mapping[]
 *     SOC_INFO(unit).port_speed_max[]
 *     SOC_INFO(unit).eq_pbm
 */
int
soc_trident_port_config_init(int unit, uint16 dev_id)
{
    soc_info_t *si;
    char *config_str, *sub_str, *sub_str_end;
    static const char str_eq[] = "EQ";
    static const char str_2p5[] = "2.5";
    char str_buf[8];
    int rv;
    int port, phy_port, mmu_port;
    int pipe, group, blk;
    int port_bandwidth, blk_bandwidth, pg_bandwidth;
    int ext_queue, index, count;
    int port_count[2], eq_port_count[2];
    int blk_port[4], blk_port_bandwidth[4];
    int eq_port[2][4], mmu_port_base[2];
    int fifo_index, fifo_count[2], extra_fifo_count[2], unused_fifo[12];
    pbmp_t pbmp_4fifo[2], pbmp_2fifo[2], pbmp_1fifo[2];


    si = &SOC_INFO(unit);

    switch (dev_id) {
    case BCM56841_DEVICE_ID:
    case BCM56842_DEVICE_ID:
    case BCM56549_DEVICE_ID:
        si->bandwidth = 320000;
        break;
    case BCM56840_DEVICE_ID:
    case BCM56843_DEVICE_ID:
    case BCM56743_DEVICE_ID:
    case BCM56844_DEVICE_ID:
    case BCM56744_DEVICE_ID:
        si->bandwidth = 480000;
        break;
    case BCM56845_DEVICE_ID:
    case BCM56745_DEVICE_ID:
    case BCM56846_DEVICE_ID:
    case BCM56746_DEVICE_ID:
        si->bandwidth = 640000;
        break;
    default:
        return SOC_E_INTERNAL;
    }

    si->port_p2l_mapping[0] = 0;    /* cpu port is logical port 0 */
    si->port_p2m_mapping[0] = 0;    /* cpu port is mmu port 0 */
    si->port_p2l_mapping[73] = 65;  /* loopback port is logical port 65 */
    si->port_p2m_mapping[73] = 33;  /* loopback port is mmu port 33 */
    for (phy_port = 1; phy_port < 73; phy_port++) {
        si->port_p2l_mapping[phy_port] = -1;
        si->port_p2m_mapping[phy_port] = -1;
    }
    for (port = 0; port < 66; port++) {
        si->port_l2p_mapping[port] = -1;
        si->port_m2p_mapping[port] = -1;
        si->port_speed_max[port] = -1;
    }
    SOC_PBMP_CLEAR(si->eq_pbm);
    SOC_PBMP_PORT_SET(si->xpipe_pbm, 0);  /* cpu port */
    SOC_PBMP_PORT_SET(si->ypipe_pbm, 65); /* loopback port */

    port_count[0] = eq_port_count[0] = 0; /* X pipe */
    port_count[1] = eq_port_count[1] = 0; /* Y pipe */

    rv = SOC_E_NONE;
    for (port = 1; port < 65; port++) {
        config_str = soc_property_port_get_str(unit, port, spn_PORTMAP);
        if (config_str == NULL) {
            continue;
        }

        /*
         * portmap.<port>=<physical port number>:<bandwidth in Gb>
         *                [:<queue config>]
         */
        sub_str = config_str;

        /* Parsing physical port number */
        phy_port = sal_ctoi(sub_str, &sub_str_end);
        if (sub_str == sub_str_end) {
            soc_cm_print("Port %d: Missing physical port information \"%s\"\n",
                         port, config_str);
            rv = SOC_E_FAIL;
            continue;
        }
        if (phy_port < 1 || phy_port > 72) {
            soc_cm_print("Port %d: Invalid physical port number %d\n",
                         port, phy_port);
            rv = SOC_E_FAIL;
            continue;
        }
        if (si->port_p2l_mapping[phy_port] != -1) {
            soc_cm_print("Port %d: Physical port %d is used by port %d\n",
                         port, phy_port, si->port_p2l_mapping[phy_port]);
            rv = SOC_E_FAIL;
            continue;
        }
        pipe = phy_port < 37 ? 0 : 1;
        if (port_count[pipe] >= 32) {
            soc_cm_print("Can not configure more than 32 port in "
                         "%c pipeline\n", pipe ? 'Y' : 'X');
            rv = SOC_E_FAIL;
            continue;
        }

        /* Skip ':' */
        sub_str = sub_str_end;
        if (*sub_str != '\0') {
            if (*sub_str != ':') {
                soc_cm_print("Port %d: Bad config string \"%s\"\n",
                             port, config_str);
                rv = SOC_E_FAIL;
                continue;
            }
            sub_str++;
        }

        /* Parsing bandwidth */
        for (index = 0; index < sizeof(str_2p5) - 1; index++) {
            if (sub_str[index] == '\0') {
                break;
            }
            str_buf[index] = sub_str[index];
        }
        str_buf[index] = '\0';
        if (!sal_strcmp(str_buf, str_2p5)) {
            port_bandwidth = 2500;
            sub_str_end = &sub_str[sizeof(str_2p5) - 1];
        } else {
            port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000;
            if (sub_str == sub_str_end) {
                soc_cm_print("Port %d: Missing bandwidth information \"%s\"\n",
                             port, config_str);
                rv = SOC_E_FAIL;
                continue;
            }
            if (port_bandwidth != 1000 && port_bandwidth != 10000 &&
                port_bandwidth != 15000 && port_bandwidth != 20000 &&
                port_bandwidth != 21000 && 
                port_bandwidth != 30000 && port_bandwidth != 40000) {
                soc_cm_print("Port %d: Invalid bandwidth %d Gb\n",
                             port, port_bandwidth / 1000);
                rv = SOC_E_FAIL;
                continue;
            }
        }

        /* Skip ':' */
        sub_str = sub_str_end;
        if (*sub_str != '\0') {
            if (*sub_str != ':') {
                soc_cm_print("Port %d: Bad config string \"%s\"\n",
                             port, config_str);
                rv = SOC_E_FAIL;
                continue;
            }
            sub_str++;
        }

        /* Parsing optional queue config */
        ext_queue = FALSE;
        for (index = 0; index < sizeof(str_eq) - 1; index++) {
            if (sub_str[index] == '\0') {
                break;
            }
            if (sub_str[index] > 'a' && sub_str[index] < 'z') {
                str_buf[index] = sub_str[index] & ~0x20;
            } else {
                str_buf[index] = sub_str[index];
            }
        }
        str_buf[index] = '\0';
        if (!sal_strcmp(str_buf, str_eq)) {
            ext_queue = TRUE;
            sub_str += sizeof(str_eq) - 1;

            if (eq_port_count[pipe] >= 4) {
                soc_cm_print("Port %d %d %d %d %d: Can not configure more than"
                             " 4 extended queue port in %c pipeline\n",
                             si->port_p2l_mapping[eq_port[pipe][0]],
                             si->port_p2l_mapping[eq_port[pipe][1]],
                             si->port_p2l_mapping[eq_port[pipe][2]],
                             si->port_p2l_mapping[eq_port[pipe][3]],
                             port, pipe ? 'Y' : 'X');
                rv = SOC_E_FAIL;
                continue;
            }
        }

        /* Checking trailing string */
        if (*sub_str != '\0') {
            soc_cm_print("Port %d: Bad config string \"%s\"\n",
                         port, config_str);
            rv = SOC_E_FAIL;
            continue;
        }

        si->port_p2l_mapping[phy_port] = port;
        si->port_l2p_mapping[port] = phy_port;
        si->port_speed_max[port] = port_bandwidth;
        port_count[pipe]++;
        if (ext_queue) {
            eq_port[pipe][eq_port_count[pipe]] = port;
            eq_port_count[pipe]++;
        }
    }

    /* Bandwidth check for ports in each XLPORT block */
    for (pipe = 0; pipe < 2; pipe++) {
        for (group = 0; group < 2; group++) {
            pg_bandwidth = 0;
            for (blk = 0; blk < (group ? 4 : 5); blk++) {
                /* Skip QGPORT (1G x 4) in XLPORT0 block (if present) */
                if (pipe == 0 && group == 0 && blk == 0) {
                    for (index = 0; index < _TD_PORTS_PER_BLK; index++) {
                        port = si->port_p2l_mapping[1 + index];
                        if (port != -1 && si->port_speed_max[port] > 1000) {
                            break;
                        }
                    }
                    if (index == _TD_PORTS_PER_BLK) {
                        continue;
                    }
                }
                blk_bandwidth = 0;
                for (index = 0; index < 4; index++) {
                    phy_port = 1 + pipe * 36 + group * 20 + blk * 4 + index;
                    port = si->port_p2l_mapping[phy_port];
                    blk_port[index] = port;
                    if (port == -1) {
                        blk_port_bandwidth[index] = 0;
                        continue;
                    }
                    blk_port_bandwidth[index] = si->port_speed_max[port];
                    if ((blk_port_bandwidth[index] > 20000 && index != 0) ||
                        (blk_port_bandwidth[index] > 10000 && (index & 1))) {
                        soc_cm_print("Port %d: Physical port %d can not be "
                                     "configured to %d Gb\n",
                                     port, phy_port,
                                     blk_port_bandwidth[index] / 1000);
                        rv = SOC_E_FAIL;
                        continue;
                    }
                    blk_bandwidth += blk_port_bandwidth[index];

                    /* 21G uses same bandwidth as 20G in higig2 mode */
                    if (blk_port_bandwidth[index] == 21000) {
                        blk_bandwidth -= 1000;
                    }
                }
                if (blk_port_bandwidth[0] > 20000) {
                    for (index = 1; index < 4; index++) {
                        if (blk_port[index] == -1) {
                            continue;
                        }
                        soc_cm_print("Port %d bandwidth %d Gb and "
                                     "port %d can not be both configured\n",
                                     blk_port[0], blk_port_bandwidth[0] / 1000,
                                     blk_port[index]);
                        rv = SOC_E_FAIL;
                    }
                } else if (blk_port_bandwidth[0] > 10000 ||
                           blk_port_bandwidth[2] > 10000) {
                    if (blk_port_bandwidth[0] > 10000 && blk_port[1] != -1) {
                        soc_cm_print("Port %d bandwidth %d Gb and "
                                     "port %d can not be both configured\n",
                                     blk_port[0],
                                     si->port_speed_max[blk_port[0]] / 1000,
                                     blk_port[1]);
                        rv = SOC_E_FAIL;
                    }
                    if (blk_port_bandwidth[2] > 10000 && blk_port[3] != -1) {
                        soc_cm_print("Port %d bandwidth %d Gb and "
                                     "port %d can not be both configured\n",
                                     blk_port[2],
                                     si->port_speed_max[blk_port[2]] / 1000,
                                     blk_port[3]);
                        rv = SOC_E_FAIL;
                    }
                    if (blk_port[0] == -1) {
                        soc_cm_print("Physical port %d needs to be configred "
                                     "in order to work with port %d\n",
                                     1 + pipe * 36 + group * 20 + blk * 4,
                                     blk_port[2]);
                        rv = SOC_E_FAIL;
                    } else if (blk_port[2] != -1 &&
                               si->port_speed_max[blk_port[0]] !=
                               si->port_speed_max[blk_port[2]]) {
                        soc_cm_print("Port %d bandwidth %d Gb can not have "
                                     "different bandwidth with port %d "
                                     "bandwidth %d Gb\n",
                                     blk_port[0],
                                     si->port_speed_max[blk_port[0]] / 1000,
                                     blk_port[2],
                                     si->port_speed_max[blk_port[2]] / 1000);
                        rv = SOC_E_FAIL;
                    }
                }
                if (blk_bandwidth > 40000) {
                    soc_cm_print("XLPORT%d bandwidth %d Gb exceed limit\n",
                                 pipe * 9 + group * 5 + blk,
                                 blk_bandwidth / 1000);
                    rv = SOC_E_FAIL;
                }
                pg_bandwidth += blk_bandwidth;
            }
            if (pg_bandwidth > si->bandwidth / 4) {
                soc_cm_print("PORT_GROUP%d_%c bandwidth %d Gb exceed limit\n",
                             group ? 4 : 5, pipe ? 'Y' : 'X',
                             pg_bandwidth / 1000);
                rv = SOC_E_FAIL;
            }
        }
    }

    if (SOC_FAILURE(rv)) {
        for (phy_port = 1; phy_port < 73; phy_port++) {
            si->port_p2l_mapping[phy_port] = -1;
        }
        return rv;
    }

    if (soc_cm_debug_check(DK_VERBOSE)) {
        soc_cm_print("physical to logical mapping:");
        for (index = 0; index < 74; index++) {
            if (index % 16 == 0) {
                soc_cm_print("\n    ");
            }
            soc_cm_print(" %3d", si->port_p2l_mapping[index]);
        }
        soc_cm_print("\n");
        soc_cm_print("physical port bandwidth:");
        for (index = 0; index < 74; index++) {
            if (index % 16 == 0) {
                soc_cm_print("\n    ");
            }
            port = si->port_p2l_mapping[index];
            if (port == -1) {
                soc_cm_print("  -1");
            } else if (si->port_speed_max[port] == 2500) {
                soc_cm_print(" 2.5");
            } else {
                soc_cm_print(" %3d", si->port_speed_max[port] / 1000);
            }
        }
        soc_cm_print("\n");
    }

    /* Assign MMU port */
    mmu_port_base[0] = 1;
    mmu_port_base[1] = 34;
    fifo_count[0] = fifo_count[1] = 0;

    /*
     * To improve multicast performace, try assigning 4 fifo (instead of 1)
     * for ports in single mode or 2 fifo for ports in dual mode. It is not
     * always possible to assign such extra fifo when special GE port in
     * XLPORT0 is in user portmap.
     */
    SOC_PBMP_CLEAR(pbmp_4fifo[0]);
    SOC_PBMP_CLEAR(pbmp_4fifo[1]);
    SOC_PBMP_CLEAR(pbmp_2fifo[0]);
    SOC_PBMP_CLEAR(pbmp_2fifo[1]);
    SOC_PBMP_CLEAR(pbmp_1fifo[0]);
    SOC_PBMP_CLEAR(pbmp_1fifo[1]);
    extra_fifo_count[0] = 0;
    extra_fifo_count[1] = 0;
    for (port = 1; port < 65; port++) {
        phy_port = si->port_l2p_mapping[port];
        if (phy_port == -1) {
            continue;
        }
        if (phy_port < 37) { /* X-pipe */
            pipe = 0;
            SOC_PBMP_PORT_ADD(si->xpipe_pbm, port);
        } else { /* Y-pipe */
            pipe = 1;
            SOC_PBMP_PORT_ADD(si->ypipe_pbm, port);
        }
        if (si->port_speed_max[port] > 20000) {
            if (port_count[pipe] + extra_fifo_count[pipe] + 3 <= 32) {
                /* has more than 3 unused fifo can be assigned to this port */
                SOC_PBMP_PORT_ADD(pbmp_4fifo[pipe], port);
                extra_fifo_count[pipe] += 3;
            } else {
                SOC_PBMP_PORT_ADD(pbmp_1fifo[pipe], port);
            }
        } else if (si->port_speed_max[port] > 10000) {
            /* has more than 1 unused fifo can be assigned to this port */
            if (port_count[pipe] + extra_fifo_count[pipe] + 1 <= 32) {
                SOC_PBMP_PORT_ADD(pbmp_2fifo[pipe], port);
                extra_fifo_count[pipe] += 1;
            } else {
                SOC_PBMP_PORT_ADD(pbmp_1fifo[pipe], port);
            }
        } else {
            SOC_PBMP_PORT_ADD(pbmp_1fifo[pipe], port);
        }
    }

    /* User specified extended queuing ports */
    for (pipe = 0; pipe < 2; pipe++) {
        for (index = 0; index < eq_port_count[pipe]; index++) {
            port = eq_port[pipe][index];
            phy_port = si->port_l2p_mapping[port];
            mmu_port = mmu_port_base[pipe] + index;
            si->port_p2m_mapping[phy_port] = mmu_port;
            si->port_m2p_mapping[mmu_port] = phy_port;
            SOC_PBMP_PORT_ADD(si->eq_pbm, port);
            fifo_count[pipe] += 4;
        }
    }

    /* Assign all 4 fifo in a MCQ group to each single mode XLPORT */
    for (pipe = 0; pipe < 2; pipe++) {
        SOC_PBMP_ITER(pbmp_4fifo[pipe], port) {
            phy_port = si->port_l2p_mapping[port];
            if (si->port_p2m_mapping[phy_port] != -1) {
                continue;
            }
            if (fifo_count[pipe] == 32) {
                break;
            }
            fifo_index = fifo_count[pipe];
            /* 1, 2, 3, 4, 17, 18, 19, 20 */
            mmu_port = mmu_port_base[pipe] +
                ((fifo_index & 0x10) | ((fifo_index & 0xc) >> 2));
            fifo_count[pipe] += 4;
            si->port_p2m_mapping[phy_port] = mmu_port;
            si->port_m2p_mapping[mmu_port] = phy_port;
        }
    }

    /* Assign 2 consective fifo in a MCQ group to each dual mode XLPORT */
    for (pipe = 0; pipe < 2; pipe++) {
        /* Find unused fifo from the user specified extended queue ports */
        count = 0;
        for (index = 0; index < eq_port_count[pipe]; index++) {
            port = eq_port[pipe][index];
            if (!SOC_PBMP_MEMBER(pbmp_4fifo[pipe], port)) {
                unused_fifo[count] = index + 8;
                count++;
            }
        }

        index = 0;
        SOC_PBMP_ITER(pbmp_2fifo[pipe], port) {
            phy_port = si->port_l2p_mapping[port];
            if (si->port_p2m_mapping[phy_port] != -1) {
                continue;
            }
            if (index < count) {
                mmu_port = mmu_port_base[pipe] + unused_fifo[index];
                index++;
            } else if (fifo_count[pipe] == 32) {
                break;
            } else {
                fifo_index = fifo_count[pipe];
                /* 1, 9, 2, 10, 3, 11, 4, 12, 17, 25, 18, 26, 19, 27, 20, 28 */
                mmu_port =  mmu_port_base[pipe] +
                    ((fifo_index & 0x10) | ((fifo_index & 0xc) >> 2) |
                     ((fifo_index & 0x2) << 2));
                fifo_count[pipe] += 2;
            }
            si->port_p2m_mapping[phy_port] = mmu_port;
            si->port_m2p_mapping[mmu_port] = phy_port;
        }
    }

    /* Assign fifo to each quad mode XLPORT */
    for (pipe = 0; pipe < 2; pipe++) {
        /* Find unused fifo from the user specified extended queue ports */
        count = 0;
        for (index = 0; index < eq_port_count[pipe]; index++) {
            port = eq_port[pipe][index];
            if (SOC_PBMP_MEMBER(pbmp_1fifo[pipe], port)) {
                unused_fifo[count] = index + 4;
                count++;
            }
            if (!SOC_PBMP_MEMBER(pbmp_4fifo[pipe], port) &&
                si->port_m2p_mapping[mmu_port_base[pipe] + index + 8] == -1) {
                unused_fifo[count] = index + 8;
                count++;
                unused_fifo[count] = index + 12;
                count++;
            }
        }

        index = 0;
        SOC_PBMP_ITER(pbmp_1fifo[pipe], port) {
            phy_port = si->port_l2p_mapping[port];
            if (si->port_p2m_mapping[phy_port] != -1) {
                continue;
            }
            if (index < count) {
                mmu_port = mmu_port_base[pipe] + unused_fifo[index];
                index++;
            } else  if (fifo_count[pipe] == 32) {
                break;
            } else {
                fifo_index = fifo_count[pipe];
                /* 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16,
                 * 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31, 20, 24,
                 * 28, 32
                 */
                mmu_port = mmu_port_base[pipe] +
                ((fifo_index & 0x10) | ((fifo_index & 0xc) >> 2) |
                 ((fifo_index & 0x3) << 2));
                fifo_count[pipe]++;
            }
            si->port_p2m_mapping[phy_port] = mmu_port;
            si->port_m2p_mapping[mmu_port] = phy_port;
        }
    }

    if (soc_cm_debug_check(DK_VERBOSE)) {
        soc_cm_print("physical to mmu mapping:");
        for (index = 0; index < 74; index++) {
            if (index % 16 == 0) {
                soc_cm_print("\n    ");
            }
            soc_cm_print(" %3d", si->port_p2m_mapping[index]);
        }
        soc_cm_print("\n");
    }

    return SOC_E_NONE;
}

STATIC void
_soc_trident_tdm_add_spacing(int target_len, int *target, int source_len,
                             int *source, int pad)
{
    int source_index, target_index;
    int result[_TD_TDM_NUM_SLOTS];

    /* Space out sequence with IDLE or NULL slot.
     *   IDLE slot occupies a space in hardware TDM table
     *   NULL slot will be removed from the merge result of this routine
     * Following is the slot usage for sprading sequence into 8 slots:
     *   40G bandwidth block: 40-40-40-40-40-40-40-40
     *   30G bandwidth block: xx-30-30-30-xx-30-30-30
     *   20G bandwidth block: xx-20-xx-20-xx-20-xx-20
     *   15G bandwidth block: xx-xx-15-xx-xx-15-xx-15
     *   10G bandwidth block: xx-xx-xx-10-xx-xx-xx-10
     *    5G bandwidth block: xx-xx-xx-xx-xx-xx-xx-5 (for 1G or 2.5G port)
     * Following is the slot usage for sprading sequence into 6 slots:
     *   30G bandwidth block: 30-30-30-30-30-30
     *   20G bandwidth block: xx-20-20-xx-20-20
     *   15G bandwidth block: xx-15-xx-15-xx-15
     *   10G bandwidth block: xx-xx-10-xx-xx-10
     *    5G bandwidth block: xx-xx-xx-xx-xx-5 (for 1G or 2.5G port)
     */
    for (target_index = 0; target_index < target_len; target_index++) {
        result[target_index] = pad;
    }
    for (source_index = 0; source_index < source_len; source_index++) {
        target_index = target_len - 1 -
            (source_len - 1 - source_index) * target_len / source_len;
        result[target_index] = source[source_index];
    }
    for (target_index = 0; target_index < target_len; target_index++) {
        target[target_index] = result[target_index];
    }
}

STATIC void
_soc_trident_tdm_merge(int target_num_seq, int target_len, int source_num_seq,
                       int padded_len0, int source_len0, int *seq0,
                       int padded_len1, int source_len1, int *seq1,
                       int padded_len2, int source_len2, int *seq2,
                       int padded_len3, int source_len3, int *seq3)
{
    int padded_len[_TD_TDM_NUM_COLUMNS], source_len[_TD_TDM_NUM_COLUMNS];
    int *seq[_TD_TDM_NUM_COLUMNS];
    int adjust_seq[_TD_TDM_NUM_COLUMNS][_TD_TDM_NUM_SLOTS];
    int seq_len, *seq_ptr;
    int column, slot, count;

    padded_len[0] = padded_len0;
    padded_len[1] = padded_len1;
    padded_len[2] = padded_len2;
    padded_len[3] = padded_len3;
    source_len[0] = source_len0;
    source_len[1] = source_len1;
    source_len[2] = source_len2;
    source_len[3] = source_len3;
    seq[0] = seq0;
    seq[1] = seq1;
    seq[2] = seq2;
    seq[3] = seq3;

    for (column = 0; column < source_num_seq; column++) {
        seq_len = source_len[column];
        seq_ptr = seq[column];
        if (padded_len[column] > seq_len) {
            /* pad with evenly distributed idle slots */
            _soc_trident_tdm_add_spacing
                (padded_len[column], adjust_seq[column], source_len[column],
                 seq[column], _TD_TDM_SLOT_IDLE);
            seq_len = padded_len[column];
            seq_ptr = adjust_seq[column];
        }
        /* pad with evenly distributed null slots */
        _soc_trident_tdm_add_spacing(target_len, adjust_seq[column], seq_len,
                                     seq_ptr, _TD_TDM_SLOT_NULL);
    }

    count = 0;
    for (slot = 0; slot < target_len; slot++) {
        for (column = 0; column < source_num_seq; column++) {
            if (adjust_seq[column][slot] != _TD_TDM_SLOT_NULL) {
                seq[count % target_num_seq][count / target_num_seq] =
                    adjust_seq[column][slot];
                count++;
            }
        }
    }
    for (; count < target_len * target_num_seq; count++) {
        seq[count % target_num_seq][count / target_num_seq] =
            _TD_TDM_SLOT_NULL;
    }
}

STATIC int
_soc_trident_calculate_tdm_sequence(int unit, int pipe, int group,
                                    int *tdm_seq, int *tdm_seq_len,
                                    int extra_port, int extra_port_bandwidth)
{
    soc_info_t *si;
    int group_min, group_max;
    int num_blk, blk_offset, blk_offset1;
    int num_col, num_row;
    int port, phy_port, index, port_index;
    int slot, slot_size, count, last_swap;
    int port_speed_max;
    int slot_count[_TD_PORTS_PER_BLK], max_slot_count;
    int blk_bandwidth[_TD_BLKS_PER_GROUP], max_blk_bandwidth;
    int blk_seq[_TD_BLKS_PER_GROUP][8], group_seq[2][32];
    int sort_blk_list[_TD_BLKS_PER_GROUP];
    int sort_blk_len[_TD_BLKS_PER_GROUP];
    int blk_count, blk_index;

    si = &SOC_INFO(unit);

    if (pipe < 0 || pipe > 1 || group < -1 || group > 1) {
        return SOC_E_FAIL;
    }

    if (group == -1) {
        group_min = 0;
        group_max = 1;
    } else {
        group_min = group_max = group;
    }

    /* Collect port information */
    sal_memset(group_seq, -1, sizeof(group_seq));
    slot_size = 5000;
    for (group = group_min; group <= group_max; group++) {
        sal_memset(sort_blk_list, -1, sizeof(sort_blk_list));
        sal_memset(blk_bandwidth, 0, sizeof(blk_bandwidth));
        sal_memset(blk_seq, -1, sizeof(blk_seq));
        blk_count = 0;
        max_blk_bandwidth = 0;
        num_blk = group ? 4 : 5;
        blk_index = pipe * _TD_BLKS_PER_PIPE + group * _TD_BLKS_PER_GROUP;
        for (blk_offset = 0; blk_offset < num_blk; blk_offset++) {
            phy_port = 1 + (blk_index + blk_offset) * _TD_PORTS_PER_BLK;
            /* Skip QGPORT (1G x 4) in XLPORT0 block (if present) */
            if (phy_port == 1) {
                for (port_index = 0; port_index < _TD_PORTS_PER_BLK;
                     port_index++) {
                    port = si->port_p2l_mapping[phy_port + port_index];
                    if (port != -1 && si->port_speed_max[port] > 1000) {
                        break;
                    }
                }
                if (port_index == _TD_PORTS_PER_BLK) {
                    continue;
                }
            }

            /* Find the number of slots needed for each port in the block */
            max_slot_count = 0;
            for (port_index = 0; port_index < _TD_PORTS_PER_BLK;
                 port_index++) {
                port = si->port_p2l_mapping[phy_port + port_index];
                if (port == -1) {
                    continue;
                }
                port_speed_max = si->port_speed_max[port];
                if (port_speed_max == 1000 || port_speed_max == 2500) {
                    port_speed_max = 5000;
                }
                blk_bandwidth[blk_offset] += port_speed_max;
                slot_count[port_index] = port_speed_max / slot_size;
                if (max_slot_count < slot_count[port_index]) {
                    max_slot_count = slot_count[port_index];
                }
            }

            if (blk_bandwidth[blk_offset] == 0) {
                continue;
            }
            if (max_blk_bandwidth < blk_bandwidth[blk_offset]) {
                max_blk_bandwidth = blk_bandwidth[blk_offset];
            }
            blk_count++;

            /* Construct per block TDM sequence */
            count = 0;
            for (slot = 0; slot < max_slot_count; slot++) {
                for (port_index = 0; port_index < _TD_PORTS_PER_BLK;
                     port_index++) {
                    port = si->port_p2l_mapping[phy_port + port_index];
                    if (port == -1) {
                        continue;
                    }
                    if (slot_count[port_index] == 0) {
                        continue;
                    }
                    blk_seq[blk_offset][count] = port;
                    slot_count[port_index]--;
                    count++;
                }
            }
        }

        if (blk_count == 0) {
            continue;
        }

        /* Sort block by bandwidth, place highest bandwidth block first */
        count = 0;
        for (blk_offset = 0; blk_offset < num_blk; blk_offset++) {
            if (blk_bandwidth[blk_offset] > 0) {
                sort_blk_list[count++] = blk_offset;
            }
        }
        do {
            last_swap = 0;
            for (index = 0; index < count - 1; index++) {
                blk_offset = sort_blk_list[index];
                blk_offset1 = sort_blk_list[index + 1];
                if (blk_bandwidth[blk_offset] >= blk_bandwidth[blk_offset1]) {
                    continue;
                }
                sort_blk_list[index] = blk_offset1;
                sort_blk_list[index + 1] = blk_offset;
                last_swap = index + 1;
            }
            count = last_swap;
        } while (count > 1);

        for (blk_index = 0; blk_index < _TD_BLKS_PER_GROUP; blk_index++) {
            blk_offset = sort_blk_list[blk_index];
            sort_blk_len[blk_index] =
                blk_offset < 0 ? 0 : blk_bandwidth[blk_offset] / slot_size;
        }

        if (si->bandwidth == 640000) { /* 640G */
            num_col = 4;
            num_row = 8;
            if (blk_count == num_col + 1) { /* need to get rid of 1 column */
                if (sort_blk_len[3] + sort_blk_len[4] <= num_row) {
                    if (sort_blk_len[3] == 6) { /* *-*-*-30-x (x <= 10) */
                        /* merge 30, (padded) 10 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             2, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0, -1, 0, 0);
                    } else { /* *-*-*-x-y (x <= 20, y <= 20) */
                        /* merge (padded) 20, (padded) 20 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             4, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             4, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0, -1, 0, 0);
                    }
                } else if (sort_blk_len[4] == 6) { /* *-30-30-30-30 */
                    /* merge 30, 30, 30, 30 into 3 columns */
                    _soc_trident_tdm_merge
                        (3, num_row, 4,
                         -1, sort_blk_len[1], blk_seq[sort_blk_list[1]],
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         -1, sort_blk_len[4], blk_seq[sort_blk_list[4]]);
                } else { /* *-*-30-30-x (x == 15 || x == 20) */
                    /* merge 30, 30, (padded) 20 into 2 columns */
                    _soc_trident_tdm_merge
                        (2, num_row, 3,
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         4, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                         -1, 0, 0);
                }
            }
        } else if (max_blk_bandwidth <= 30000) {  /* 480G/320G case 1 */
            num_col = 4;
            num_row = 6;
            if (blk_count == num_col + 1) { /* need to get rid of 1 column */
                if (sort_blk_len[3] + sort_blk_len[4] <= num_row) {
                    if (sort_blk_len[3] == 4) { /* *-*-*-20-x (x <= 10) */
                        /* merge 20, (padded) 10 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             2, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0, -1, 0, 0);
                    } else { /* *-*-*-x-y (x <= 15, y <= 15) */
                        /* merge (padded) 15, (padded) 15 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             3, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             3, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0, -1, 0, 0);
                    }
                } else { /* *-*-20-20-x (x == 15 || x == 20) */
                    /* merge 20, 20, (padded) 20 into 2 columns */
                    _soc_trident_tdm_merge
                        (2, num_row, 3,
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         4, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                         -1, 0, 0);
                }
            }
        } else { /* 480G/320G case 2 */
            num_col = 3;
            num_row = 8;
            if (blk_count == num_col + 1) { /* need to get rid of 1 column */
                if (sort_blk_len[2] + sort_blk_len[3] <= num_row) {
                    if (sort_blk_len[2] == 6) { /* 40-*-30-x (x <= 10) */
                        /* merge 30, (padded) 10 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                             2, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             -1, 0, 0, -1, 0, 0);
                    } else { /* 40-*-x-y (x <= 20, y <= 20) */
                        /* merge (padded) 20, (padded) 20 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             4, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                             4, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             -1, 0, 0, -1, 0, 0);
                    }
                } else { /* 40-30-30-x (x == 15 || x == 20) */
                    /* merge 30, 30, (padded) 20 into 2 columns */
                    _soc_trident_tdm_merge
                        (2, num_row, 3,
                         -1, sort_blk_len[1], blk_seq[sort_blk_list[1]],
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         4, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         -1, 0, 0);
                }
            } else if (blk_count == num_col + 2) {
                /* need to get rid of 2 columns */
                if (sort_blk_len[2] + sort_blk_len[3] + sort_blk_len[4] <=
                    num_row) {
                    if (sort_blk_len[2] >= 4) { /* 40-*-x-y-z (x >= 20) */
                        /* first merge columns 3 and 4 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             -1, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0, -1, 0, 0);
                        /* then merge columns 2 and merged 3+4 into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 2,
                             -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                             -1, sort_blk_len[3] + sort_blk_len[4],
                             blk_seq[sort_blk_list[3]],
                             -1, 0, 0, -1, 0, 0);
                    } else { /* 40-*-x-y-z (x < 20) */
                        /* directly merge all 3 columns into 1 column */
                        _soc_trident_tdm_merge
                            (1, num_row, 3,
                             -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                             -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                             -1, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                             -1, 0, 0);
                    }
                } else if (sort_blk_len[1] + sort_blk_len[4] <= 8  &&
                           sort_blk_len[2] + sort_blk_len[3] <= 8) {
                    /* merge columns 1 and 4 into 1 column */
                    _soc_trident_tdm_merge
                        (1, num_row, 2,
                         -1, sort_blk_len[1], blk_seq[sort_blk_list[1]],
                         -1, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                         -1, 0, 0, -1, 0, 0);
                    /* merge columns 2 and 3 into 1 column */
                    _soc_trident_tdm_merge
                        (1, num_row, 2,
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         -1, 0, 0, -1, 0, 0);
                } else if (sort_blk_len[2] == 6) { /* 40-30-30-15-5 */
                    /* first merge columns 3 and 4 into 1 column */
                    _soc_trident_tdm_merge
                        (1, num_row, 2,
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         -1, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                         -1, 0, 0, -1, 0, 0);
                    /* then merge 30, 30, merged 3+4 into 2 columns */
                    _soc_trident_tdm_merge
                        (2, num_row, 3,
                         -1, sort_blk_len[1], blk_seq[sort_blk_list[1]],
                         -1, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, sort_blk_len[3] + sort_blk_len[4],
                         blk_seq[sort_blk_list[3]],
                         -1, 0, 0);
                } else { /* 40-30-x-15-15 (x == 15 || x == 20) */
                    /* first merge columns 3 and 4 into 1 column */
                    _soc_trident_tdm_merge
                        (1, num_row, 2,
                         -1, sort_blk_len[3], blk_seq[sort_blk_list[3]],
                         -1, sort_blk_len[4], blk_seq[sort_blk_list[4]],
                         -1, 0, 0, -1, 0, 0);
                    /* then merge 30, merged 3+4, (padded) 20 into 2 columns */
                    _soc_trident_tdm_merge
                        (2, num_row, 3,
                         -1, sort_blk_len[1], blk_seq[sort_blk_list[1]],
                         -1, sort_blk_len[3] + sort_blk_len[4],
                         blk_seq[sort_blk_list[3]],
                         4, sort_blk_len[2], blk_seq[sort_blk_list[2]],
                         -1, 0, 0);
                }
            }
        }

        if (blk_count <= num_col) {
            /* If no merge was done, just evenly distributed the sequence
             * in each block */
            for (blk_index = 0; blk_index < num_col; blk_index++) {
                blk_offset = sort_blk_list[blk_index];
                if (blk_offset < 0) {
                    break;
                }
                _soc_trident_tdm_add_spacing
                    (num_row, blk_seq[blk_offset], sort_blk_len[blk_index],
                     blk_seq[blk_offset], _TD_TDM_SLOT_IDLE);
            }
        }

        for (blk_index = 0; blk_index < num_col; blk_index++) {
            blk_offset = sort_blk_list[blk_index];
            if (blk_offset < 0) {
                break;
            }
            for (index = 0; index < num_row; index++) {
                group_seq[group][index * num_col + blk_index] =
                    blk_seq[blk_offset][index];
            }
        }
    }

    /* Construct final TDM sequence from 2 group TDM sequences */
    count = si->bandwidth == 640000 ? 32 : 24;
    index = 0;
    for (slot = 0; slot < count; slot++) {
        for (group = group_min; group <= group_max; group++) {
            tdm_seq[index++] = group_seq[group][slot];
        }
        if (extra_port != -1) {
            if (slot == count - 1 ||
                (extra_port_bandwidth == 10000 && slot == count / 2 - 1)) {
                tdm_seq[index++] = extra_port;
            }
        }
    }
    *tdm_seq_len = index;

    return SOC_E_NONE;
}

STATIC int
_soc_trident_pg_tdm_init(int unit)
{
    static const soc_field_t tdm_field[] = {
        TDM_ENTRY0_PORT_IDf, TDM_ENTRY1_PORT_IDf, TDM_ENTRY2_PORT_IDf,
        TDM_ENTRY3_PORT_IDf, TDM_ENTRY4_PORT_IDf, TDM_ENTRY5_PORT_IDf,
        TDM_ENTRY6_PORT_IDf, TDM_ENTRY7_PORT_IDf, TDM_ENTRY8_PORT_IDf,
        TDM_ENTRY9_PORT_IDf, TDM_ENTRY10_PORT_IDf, TDM_ENTRY11_PORT_IDf,
        TDM_ENTRY12_PORT_IDf, TDM_ENTRY13_PORT_IDf, TDM_ENTRY14_PORT_IDf,
        TDM_ENTRY15_PORT_IDf, TDM_ENTRY16_PORT_IDf, TDM_ENTRY17_PORT_IDf,
        TDM_ENTRY18_PORT_IDf, TDM_ENTRY19_PORT_IDf, TDM_ENTRY20_PORT_IDf,
        TDM_ENTRY21_PORT_IDf, TDM_ENTRY22_PORT_IDf, TDM_ENTRY23_PORT_IDf,
        TDM_ENTRY24_PORT_IDf, TDM_ENTRY25_PORT_IDf, TDM_ENTRY26_PORT_IDf,
        TDM_ENTRY27_PORT_IDf, TDM_ENTRY28_PORT_IDf, TDM_ENTRY29_PORT_IDf,
        TDM_ENTRY30_PORT_IDf, TDM_ENTRY31_PORT_IDf
    };
    static const soc_reg_t tdm_reg[2][8] = {
        {
            PORT_GROUP5_TDM_REG_0r, PORT_GROUP5_TDM_REG_1r,
            PORT_GROUP5_TDM_REG_2r, PORT_GROUP5_TDM_REG_3r,
            PORT_GROUP5_TDM_REG_4r, PORT_GROUP5_TDM_REG_5r,
            PORT_GROUP5_TDM_REG_6r, PORT_GROUP5_TDM_REG_7r
        },
        {
            PORT_GROUP4_TDM_REG_0r, PORT_GROUP4_TDM_REG_1r,
            PORT_GROUP4_TDM_REG_2r, PORT_GROUP4_TDM_REG_3r,
            PORT_GROUP4_TDM_REG_4r, PORT_GROUP4_TDM_REG_5r,
            PORT_GROUP4_TDM_REG_6r, PORT_GROUP4_TDM_REG_7r
        }
    };
    static const soc_reg_t tdm_control[2] = {
        PORT_GROUP5_TDM_CONTROLr, PORT_GROUP4_TDM_CONTROLr
    };
    soc_info_t *si;
    soc_reg_t reg;
    soc_field_t field;
    uint32 rval;
    int rv, pipe, group, port, phy_port, index;
    int tdm_seq[32], tdm_seq_len;

    si = &SOC_INFO(unit);

    for (pipe = 0; pipe < 2; pipe++) {
        for (group = 0; group < 2; group++) {
            rv = _soc_trident_calculate_tdm_sequence(unit, pipe, group,
                                                     tdm_seq, &tdm_seq_len, -1,
                                                     0);
            if (rv == SOC_E_EMPTY) {
                continue;
            } else if (SOC_FAILURE(rv)) {
                return rv;
            }
            if (soc_cm_debug_check(DK_VERBOSE)) {
                soc_cm_print("PORT_GROUP%c_%c TDM:",
                             group ? '4' : '5', pipe ? 'Y' : 'X');
                for (index = 0; index < tdm_seq_len; index++) {
                    if (index % 16 == 0) {
                        soc_cm_print("\n    ");
                    }
                    soc_cm_print(" %2d", tdm_seq[index]);
                }
                soc_cm_print("\n");
            }
            rval = 0;
            for (index = 0; index < tdm_seq_len; index++) {
                reg = tdm_reg[group][index / 4];
                field = tdm_field[index];
                port = tdm_seq[index];
                if (port != _TD_TDM_SLOT_IDLE && port != _TD_TDM_SLOT_NULL) {
                    phy_port = si->port_l2p_mapping[port];
                    soc_reg_field_set(unit, reg, &rval, field, phy_port);
                } else {
                    soc_reg_field_set(unit, reg, &rval, field, 0x7f);
                }
                if (index % 4 == 3 || index == tdm_seq_len - 1) {
                    SOC_IF_ERROR_RETURN
                        (soc_reg32_set(unit, reg, pipe, 0, rval));
                    rval = 0;
                }
            }
            reg = tdm_control[group];
            rval = 0;
            soc_reg_field_set(unit, reg, &rval, TDM_WRAP_PTRf,
                              tdm_seq_len - 1);
            SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pipe, 0, rval));
        }
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_mmu_tdm_init(int unit)
{
    static const soc_mem_t tdm_mem[] = {
        ARB_TDM_TABLE_0m, ARB_TDM_TABLE_1m
    };
    soc_info_t *si;
    soc_mem_t mem;
    union {
        arb_tdm_table_0_entry_t table_0;
        arb_tdm_table_1_entry_t table_1;
    } entry;
    int rv, pipe, port, phy_port, mmu_port, index, base;
    int tdm_seq[128], tdm_seq_len;
    int extra_port;

    si = &SOC_INFO(unit);

    for (pipe = 0; pipe < 2; pipe++) {
        if (pipe == 0) { /* X pipe */
            extra_port = 0;
            base = 0;
        } else { /* Y pipe */
            extra_port = 65;
            base = 33;
        }
        rv = _soc_trident_calculate_tdm_sequence(unit, pipe, -1, tdm_seq,
                                                 &tdm_seq_len, extra_port,
                                                 si->bandwidth == 640000 ?
                                                 5000 : 10000);
        if (rv == SOC_E_EMPTY) {
            continue;
        } else if (SOC_FAILURE(rv)) {
            return rv;
        }
        if (soc_cm_debug_check(DK_VERBOSE)) {
            soc_cm_print("%c pipe MMU TDM:", pipe ? 'Y' : 'X');
            for (index = 0; index < tdm_seq_len; index++) {
                if (index % 16 == 0) {
                    soc_cm_print("\n    ");
                }
                soc_cm_print(" %2d", tdm_seq[index]);
            }
            soc_cm_print("\n");
        }

        mem = tdm_mem[pipe];
        sal_memset(&entry, 0, sizeof(entry));
        for (index = 0; index < tdm_seq_len; index++) {
            port = tdm_seq[index];
            if (port != _TD_TDM_SLOT_IDLE && port != _TD_TDM_SLOT_NULL) {
                phy_port = si->port_l2p_mapping[port];
                mmu_port = si->port_p2m_mapping[phy_port];
                soc_mem_field32_set(unit, mem, &entry, PORT_NUMf,
                                    mmu_port - base);
            } else {
                soc_mem_field32_set(unit, mem, &entry, PORT_NUMf, 0x3f);
            }
            if (index == tdm_seq_len - 1) {
                soc_mem_field32_set(unit, mem, &entry, WRAP_ENf, 1);
            }
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
        }
    }

    return SOC_E_NONE;
}

extern int (*_phy_wc40_firmware_set_helper)(int, int, uint8 *,int);
static void *_trident_wc_ucode_dma_buf;
static int _trident_wc_ucode_alloc_size;

int
trident_wc40_firmware_set(int unit, int port, uint8 *array,int datalen)
{
    int entry_bytes, entry_words;
    int blk;
    int count, extra_bytes, i, j, k;
    uint8 *array_ptr, *dma_buf_ptr;

    entry_bytes = soc_mem_entry_bytes(unit, XLPORT_WC_UCMEM_DATAm);
    entry_words = BYTES2WORDS(entry_bytes);

    if (_trident_wc_ucode_dma_buf == NULL) {
        count = datalen / entry_bytes;
        extra_bytes = datalen % entry_bytes;
        _trident_wc_ucode_alloc_size = datalen;
        if (extra_bytes != 0) {
            _trident_wc_ucode_alloc_size += entry_bytes - extra_bytes;
        }
        _trident_wc_ucode_dma_buf =
            soc_cm_salloc(unit, _trident_wc_ucode_alloc_size,
                          "WC ucode DMA buffer");
        if (_trident_wc_ucode_dma_buf == NULL) {
            return SOC_E_MEMORY;
        }
        array_ptr = array;
        dma_buf_ptr = _trident_wc_ucode_dma_buf;
        for (i = 0; i < count; i++) {
            for (j = 0; j < 16; j += 4) {
                for (k = 0; k < 4; k++) {
                    dma_buf_ptr[entry_bytes - sizeof(uint32) - j + k] =
                        array_ptr[j + k];
                }
            }
            array_ptr += entry_bytes;
            dma_buf_ptr += entry_bytes;
        }
        if (extra_bytes != 0) {
            sal_memset(dma_buf_ptr, 0, entry_bytes);
            for (j = 0; j < extra_bytes; j += 4) {
                for (k = 0; k < 4 && j + k < extra_bytes; k++) {
                    dma_buf_ptr[entry_bytes - sizeof(uint32) - j + k] =
                        array_ptr[j + k];
                }
            }
        }
    }

    /* enable parallel bus access */
    SOC_IF_ERROR_RETURN
        (soc_reg_field32_modify(unit, XLPORT_WC_UCMEM_CTRLr, port,
                                ACCESS_MODEf, 1));

    blk = SOC_PORT_BLOCK(unit, SOC_INFO(unit).port_l2p_mapping[port]);

    /*
     * The byte order in each 128-bit XLPORT_WC_UCMEM_DATA entry is:
     * bit position: (bit 31-0)  - (bit 63-32) - (bit 95-64) - (bit 127-96)
     * byte offset:  0c 0d 0e 0f - 08 09 0a 0b - 04 05 06 07 - 00 01 02 03
     */
    SOC_IF_ERROR_RETURN
        (soc_mem_write_range(unit, XLPORT_WC_UCMEM_DATAm, blk, 0,
                             _trident_wc_ucode_alloc_size / entry_bytes - 1,
                             _trident_wc_ucode_dma_buf));

    /* disable parallel bus access, and enable MDIO access */
    SOC_IF_ERROR_RETURN
        (soc_reg_field32_modify(unit, XLPORT_WC_UCMEM_CTRLr, port,
                                ACCESS_MODEf, 0));

    return SOC_E_NONE;
}

STATIC int
_trident_ledup_init(int unit)
{
    int ix;
    uint32 rval = 0;
    struct led_remap {
       uint32 reg_addr;
       uint32 port0;
       uint32 port1;
       uint32 port2;
       uint32 port3;
    } led1_remap[] = {
        {CMIC_LEDUP1_PORT_ORDER_REMAP_0_3r,
                    REMAP_PORT_0f,REMAP_PORT_1f,REMAP_PORT_2f,REMAP_PORT_3f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_4_7r,
                    REMAP_PORT_4f,REMAP_PORT_5f,REMAP_PORT_6f,REMAP_PORT_7f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_8_11r,
                    REMAP_PORT_8f,REMAP_PORT_9f,REMAP_PORT_10f,REMAP_PORT_11f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_12_15r,
                    REMAP_PORT_12f,REMAP_PORT_13f,REMAP_PORT_14f,REMAP_PORT_15f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_16_19r,
                    REMAP_PORT_16f,REMAP_PORT_17f,REMAP_PORT_18f,REMAP_PORT_19f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_20_23r,
                    REMAP_PORT_20f,REMAP_PORT_21f,REMAP_PORT_22f,REMAP_PORT_23f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_24_27r,
                    REMAP_PORT_24f,REMAP_PORT_25f,REMAP_PORT_26f,REMAP_PORT_27f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_28_31r,
                    REMAP_PORT_28f,REMAP_PORT_29f,REMAP_PORT_30f,REMAP_PORT_31f},
        {CMIC_LEDUP1_PORT_ORDER_REMAP_32_35r,
                    REMAP_PORT_32f,REMAP_PORT_33f,REMAP_PORT_34f,REMAP_PORT_35f}
    };

    /* initialize the led1 remap register settings to match the led0's default.
     * port 0 entry will not be used for easy index of the physical port starting 1
     */   
    for (ix = 0; ix < sizeof(led1_remap)/sizeof(led1_remap[0]); ix++) {
        rval = 0;
        soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 
                         led1_remap[ix].port0, 36 - ix * 4);
        soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 
                         led1_remap[ix].port1, 35 - ix * 4);
        soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 
                         led1_remap[ix].port2, 34 - ix * 4);
        soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 
                         led1_remap[ix].port3, 33 - ix * 4);
        SOC_IF_ERROR_RETURN
            (soc_pci_write(unit, 
                soc_reg_addr(unit, led1_remap[ix].reg_addr, REG_PORT_ANY, 0), 
                rval));
    }

    /* set the LED scanchain start address */
    rval = 0x4A;
    SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP0_SCANCHAIN_ASSEMBLY_ST_ADDRr(unit, rval));
    SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP1_SCANCHAIN_ASSEMBLY_ST_ADDRr(unit, rval));

    /* configure the LED scan delay cycles */
    SOC_IF_ERROR_RETURN(READ_CMIC_LEDUP0_CTRLr(unit, &rval));
    soc_reg_field_set(unit, CMIC_LEDUP0_CTRLr, &rval, LEDUP_SCAN_START_DELAYf, 11);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP0_CTRLr(unit, rval));

    SOC_IF_ERROR_RETURN(READ_CMIC_LEDUP1_CTRLr(unit, &rval));
    soc_reg_field_set(unit, CMIC_LEDUP1_CTRLr, &rval, LEDUP_SCAN_START_DELAYf, 15);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP1_CTRLr(unit, rval));

    /* initialize the UP0 and UP1 data ram */
    rval = 0;
    for (ix = 0; ix < 256; ix++) {
        SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP0_DATA_RAMr(unit,ix, rval));
        SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP1_DATA_RAMr(unit,ix, rval));
    }
    return SOC_E_NONE;  
}

STATIC int
_soc_trident_misc_init(int unit)
{
    static const soc_field_t port_field[4] = {
        PORT0f, PORT1f, PORT2f, PORT3f
    };
    static const soc_field_t mac_mode_field[4] = {
        PORT0_MAC_MODEf, PORT1_MAC_MODEf, PORT2_MAC_MODEf, PORT3_MAC_MODEf
    };
    static int rtag7_field_width[] = { 16, 16, 4, 16, 8, 8, 16, 16 };
    soc_info_t *si;
    uint32 rval;
    uint32 entry[SOC_MAX_MEM_WORDS];
    soc_pbmp_t pbmp;
    int port, phy_port, blk_port, blk, bindex;
    uint32 core_mode, phy_mode;
    int num_lanes;
    int blk_bandwidth;
    int index, count, sub_sel, offset;
    int divisor, dividend, delay;
    uint64 reg64;
    uint16 dev_id;
    uint8 rev_id;
    int parity_enable;
    static soc_field_t fields[2] = {HGTRUNK_RES_ENf, LAG_RES_ENf};
    uint32 values[2] = {1, 1};

    soc_cm_get_id(unit, &dev_id, &rev_id);

    si = &SOC_INFO(unit);

    parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
    if (parity_enable) {
        (void) _soc_trident_ser_init(unit);
    }

    if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) {
        SOC_IF_ERROR_RETURN(_soc_trident_clear_all_memory(unit));
    }

    if (parity_enable) {
        (void)_soc_trident_parity_enable_all(unit, TRUE);
    }

    _soc_trident_port_mapping_init(unit);

    sal_memset(entry, 0, sizeof(cpu_pbm_entry_t));
    soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit));
    SOC_IF_ERROR_RETURN
        (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry));

    sal_memset(entry, 0, sizeof(cpu_pbm_2_entry_t));
    soc_mem_pbmp_field_set(unit, CPU_PBM_2m, entry, BITMAPf, &PBMP_CMIC(unit));
    SOC_IF_ERROR_RETURN
        (soc_mem_write(unit, CPU_PBM_2m, MEM_BLOCK_ALL, 0, entry));

    sal_memset(entry, 0, sizeof(isbs_port_to_pipe_mapping_entry_t));
    soc_mem_pbmp_field_set(unit, ISBS_PORT_TO_PIPE_MAPPINGm, entry, BITMAPf,
                           &PBMP_YPIPE(unit));
    SOC_IF_ERROR_RETURN(soc_mem_write(unit, ISBS_PORT_TO_PIPE_MAPPINGm,
                                      MEM_BLOCK_ALL, 0, entry));

    sal_memset(entry, 0, sizeof(esbs_port_to_pipe_mapping_entry_t));
    soc_mem_pbmp_field_set(unit, ESBS_PORT_TO_PIPE_MAPPINGm, entry, BITMAPf,
                           &PBMP_YPIPE(unit));
    SOC_IF_ERROR_RETURN(soc_mem_write(unit, ESBS_PORT_TO_PIPE_MAPPINGm,
                                      MEM_BLOCK_ALL, 0, entry));

    sal_memset(entry, 0, sizeof(egr_ing_port_entry_t));
    soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1);
    PBMP_HG_ITER(unit, port) {
        SOC_IF_ERROR_RETURN
            (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
    }
    SOC_IF_ERROR_RETURN
        (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index,
                       entry));
    soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2);
    SOC_IF_ERROR_RETURN
        (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, LB_PORT(unit),
                       entry));

    PBMP_PORT_ITER(unit, port) {
        SOC_IF_ERROR_RETURN(READ_XLPORT_CONFIGr(unit, port, &rval));
        if (IS_HG_PORT(unit, port)) {
            soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG_MODEf, 1); 
            soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, XPAUSE_RX_ENf, 1);
            soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, XPAUSE_TX_ENf, 1);
            soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, XPAUSE_ENf, 1);
        }
        SOC_IF_ERROR_RETURN(WRITE_XLPORT_CONFIGr(unit, port, rval));
    }

    SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
        blk_port = SOC_BLOCK_PORT(unit, blk);
        if (blk_port < 0) {
            continue;
        }
        /*
         * Program XLPORT mode and default Warpcore lanes setting
         * core_mode: the number of ports on the system side of XMAC
         * phy_mode: the number of ports on the Warpcore side of XMAC
         * num_lanes: the number of lanes on the line side of Warpcore
         */
        if (si->port_speed_max[blk_port] > 20000) {
            core_mode = 0; /* single, XMAC works as a single MAC */
            phy_mode = 0; /* single, use all 16 lanes for a port */
            num_lanes = 4;
        } else if (si->port_speed_max[blk_port] > 10000) {
            core_mode = 1; /* dual, XMAC works as 2 MACs */
            phy_mode = 1; /* dual, use 8 lanes per port  */
            num_lanes = 2;
        } else {
            core_mode = 2; /* quad, XMAC works as 4 MACs */
            phy_mode = 2; /* quad, use 4 lanes per port */
            num_lanes = 1;
        }
        rval = 0;
        soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, CORE_PORT_MODEf,
                          core_mode);
        soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, PHY_PORT_MODEf,
                          phy_mode);
        phy_port = ((si->port_l2p_mapping[blk_port] - 1) & ~0x3) + 1;
        for (bindex = 0; bindex < 4; bindex++) {
            port = si->port_p2l_mapping[phy_port + bindex];
            if (port == -1) {
                continue;
            }
            if (si->port_speed_max[port] < 10000) {
                soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval,
                                  mac_mode_field[bindex], 1);
            }
            si->port_num_lanes[port] = num_lanes;
        }
        SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, blk_port, rval));

        /* Enable XLPORT */
        rval = 0;
        for (bindex = 0; bindex < 4; bindex++) {
            if (si->port_p2l_mapping[phy_port + bindex] != -1) {
                soc_reg_field_set(unit, XLPORT_PORT_ENABLEr, &rval,
                                  port_field[bindex], 1);
            }
        }
        SOC_IF_ERROR_RETURN(WRITE_XLPORT_PORT_ENABLEr(unit, blk_port, rval));
    }

    /* Enable QGPORT (1G x 4) in XLPORT0 block (if present) */
    blk_bandwidth = 0;
    for (phy_port = 1; phy_port < 5; phy_port++) {
        port = si->port_p2l_mapping[phy_port];
        if (port != -1) {
            blk_bandwidth += si->port_speed_max[port];
        }
    }
    if (blk_bandwidth > 0 && blk_bandwidth <= 4000) {
        rval = 0;
        soc_reg_field_set(unit, PORT_GROUP5_QGPORT_ENABLEr, &rval,
                          QGPORT_ENABLEf, 1);
        SOC_IF_ERROR_RETURN(WRITE_PORT_GROUP5_QGPORT_ENABLEr(unit, 0, rval));
    }

    /* Setup TDM within each port group */
    SOC_IF_ERROR_RETURN(_soc_trident_pg_tdm_init(unit));

    /* Setup main TDM between each port group */
    sal_memset(entry, 0, sizeof(iarb_main_tdm_entry_t));
    count = si->bandwidth == 640000 ? 64 : 32;
    for (index = 0; index < count; index++) {
        soc_mem_field32_set(unit, IARB_MAIN_TDMm, entry, TDM_SLOTf, index & 1);
        SOC_IF_ERROR_RETURN
            (soc_mem_write(unit, IARB_MAIN_TDMm, MEM_BLOCK_ALL, index, entry));
    }
    soc_mem_field32_set(unit, IARB_MAIN_TDMm, entry, TDM_SLOTf, 2);
    SOC_IF_ERROR_RETURN
        (soc_mem_write(unit, IARB_MAIN_TDMm, MEM_BLOCK_ALL, count, entry));

    /* Setup main TDM control */
    SOC_IF_ERROR_RETURN(READ_IARB_TDM_CONTROLr(unit, &rval));
    /* BCMSIM handles Single Cell packets */
    if (SAL_BOOT_BCMSIM) {
        soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 1);
    } else {
        soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 0);
    }
    soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, count);
    SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval));

    /* Setup EGR_PERQ_XMT_COUNTERS_BASE_ADDR for each port */
    _soc_trident_egr_perq_xmt_counters_init(unit);

    SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
    soc_reg_field_set(unit, MISCCONFIGr, &rval, METERING_CLK_ENf, 1);
    SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));

    if (soc_reg_field_valid(unit, ARB_EOP_DEBUGr, ISW2_TD_B0f)) {
        SOC_IF_ERROR_RETURN
            (soc_reg_field32_modify(unit, ARB_EOP_DEBUGr, REG_PORT_ANY,
                                    ISW2_TD_B0f, 1));
    }

    if (SOC_SWITCH_BYPASS_MODE(unit) == SOC_SWITCH_BYPASS_MODE_L3_AND_FP) {
        rval = 0;
        soc_reg_field_set(unit, ING_BYPASS_CTRLr, &rval, IFP_BYPASS_ENABLEf,
                          1);
        SOC_IF_ERROR_RETURN(WRITE_ING_BYPASS_CTRLr(unit, rval));

        rval = 0;
        soc_reg_field_set(unit, EGR_BYPASS_CTRLr, &rval, EFP_BYPASSf, 1);
        SOC_IF_ERROR_RETURN(WRITE_EGR_BYPASS_CTRLr(unit, rval));
    }

    /*
     * Egress Enable
     */
    sal_memset(entry, 0, sizeof(egr_enable_entry_t));
    soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
    PBMP_ALL_ITER(unit, port) {
        phy_port = si->port_l2p_mapping[port];
        SOC_IF_ERROR_RETURN
            (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
    }

    sal_memset(entry, 0, sizeof(epc_link_bmap_entry_t));
    soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
                           &PBMP_CMIC(unit));
    SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, entry));


    SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &reg64));
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          L3SRC_HIT_ENABLEf, 1);
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          L2DST_HIT_ENABLEf, 1);
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          APPLY_EGR_MASK_ON_L2f, 1);
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          APPLY_EGR_MASK_ON_L3f, 1);
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          ARP_VALIDATION_ENf, 1);
    soc_reg64_field32_set(unit, ING_CONFIG_64r, &reg64,
                          IGNORE_HG_HDR_LAG_FAILOVERf, 1);
    SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, reg64));

    SOC_IF_ERROR_RETURN
        (soc_reg_field32_modify(unit, EGR_CONFIG_1r, REG_PORT_ANY, RING_MODEf,
                                1));

    /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which
     * causes the outer tag to be removed from packets that don't have
     * a hit in the egress vlan tranlation table. Set to 0 to disable this.
     */
    rval = 0;
    soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, VT_MISS_UNTAGf, 0);

    /* Enable pri/cfi remarking on egress ports. */
    soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf,
                      1);
    PBMP_ALL_ITER(unit, port) {
        SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval));
    }

    SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
    SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit));
    SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm,
                                     MEM_BLOCK_ANY, 0, &entry));
    soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf,
                           &pbmp);
    SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm,
                                      MEM_BLOCK_ANY, 0, &entry));

    /* Multicast range initialization */
    SOC_IF_ERROR_RETURN
        (soc_hbx_higig2_mcast_sizes_set(unit,
             soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE,
                              SOC_HBX_MULTICAST_RANGE_DEFAULT),
             soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE,
                              SOC_HBX_MULTICAST_RANGE_DEFAULT),
             soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE,
                              SOC_HBX_MULTICAST_RANGE_DEFAULT)));
    SOC_IF_ERROR_RETURN
        (soc_hbx_mcast_size_set(unit, soc_property_get(unit,
             spn_MULTICAST_L2_RANGE, SOC_HBX_MULTICAST_RANGE_DEFAULT)));
    SOC_IF_ERROR_RETURN
        (soc_hbx_ipmc_size_set(unit, soc_property_get(unit,
             spn_MULTICAST_L3_RANGE, soc_mem_index_count(unit, L3_IPMCm))));

    /* Setup SW2_FP_DST_ACTION_CONTROL */
    SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit,
        SW2_FP_DST_ACTION_CONTROLr, REG_PORT_ANY, 2, fields, values));

    /* Populate and enable RTAG7 macro flow offset table */
    if (soc_mem_is_valid(unit, RTAG7_FLOW_BASED_HASHm)) {
        count = soc_mem_index_max(unit, RTAG7_FLOW_BASED_HASHm);
        sal_memset(entry, 0, sizeof(rtag7_flow_based_hash_entry_t));
        for (index = 0; index < count; ) {
            for (sub_sel = 0; sub_sel < 8 && index < count; sub_sel++) {
                for (offset = 0;
                     offset < rtag7_field_width[sub_sel] && index < count;
                     offset++) {
                    soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
                                        SUB_SEL_ECMPf, sub_sel);
                    soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
                                        OFFSET_ECMPf, offset);
                    SOC_IF_ERROR_RETURN
                        (soc_mem_write(unit, RTAG7_FLOW_BASED_HASHm,
                                       MEM_BLOCK_ANY, index, &entry));
                    index++;
                }
            }
        }
        rval = 0;
        soc_reg_field_set(unit, RTAG7_HASH_ECMPr, &rval, USE_FLOW_HASHf, 1);
        for (index = 0; index < 2; index++) {
            SOC_IF_ERROR_RETURN(WRITE_RTAG7_HASH_ECMPr(unit, index, rval));
        }
        rval = 0;
        soc_reg_field_set(unit, RTAG7_HASH_TRILL_ECMPr, &rval, USE_FLOW_HASHf,
                          1);
        for (index = 0; index < 2; index++) {
            SOC_IF_ERROR_RETURN
                (WRITE_RTAG7_HASH_TRILL_ECMPr(unit, index, rval));
        }
    }

    /*
     * Set I2C freq to 128KHz (495MHz) or 108KHz (415MHz)
     * target_freq = core_clock_freq * DIVIDEND / DIVISOR / CCR_divisor / 10
     * CCR_divosor = (M + 1) * 2 ** (N + 1)
     * The write only CCR register is at the same address as CMIC_I2C_STAT
     * M is bit [6:3] of CCR register
     * N is bit [2:0] of CCR register
     */
    rval = 0x10; /* M=2, N=0, CCR_divisor = (2+1)*2**(0+1)=6 */
    SOC_IF_ERROR_RETURN(WRITE_CMIC_I2C_STATr(unit, rval));

    rval = 0;
    soc_reg_field_set(unit, CMIC_RATE_ADJUST_I2Cr, &rval, DIVISORf, 64);
    soc_reg_field_set(unit, CMIC_RATE_ADJUST_I2Cr, &rval, DIVIDENDf, 1);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_I2Cr(unit, rval));

    rval = 0;
    soc_reg_field_set(unit, CMIC_RATE_ADJUST_STDMAr, &rval, DIVISORf, 16);
    soc_reg_field_set(unit, CMIC_RATE_ADJUST_STDMAr, &rval, DIVIDENDf, 1);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_STDMAr(unit, rval));

    /*
     * Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz)
     * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2
     */
    divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, 40);
    dividend = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVIDEND, 1);
    rval = 0;
    soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVISORf, divisor);
    soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVIDENDf, dividend);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUSTr(unit, rval));

    /*
     * Set internal MDIO freq to 16.5MHz (495MHz) or 13.83MHz (415MHz)
     * Valid range is from 2.5MHz to 20MHz
     * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2
     */
    rval = 0;
    soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVISORf, 15);
    soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVIDENDf, 1);
    SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_INT_MDIOr(unit, rval));

    delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, -1);
    if (delay >= 1  && delay <= 7) {
        SOC_IF_ERROR_RETURN(READ_CMIC_CONFIGr(unit, &rval));
        soc_reg_field_set(unit, CMIC_CONFIGr, &rval, MDIO_OUT_DELAYf, delay);
        SOC_IF_ERROR_RETURN(WRITE_CMIC_CONFIGr(unit, rval));
    }

    /* initialize LED UP0 and LED UP1 */
    SOC_IF_ERROR_RETURN(_trident_ledup_init(unit));

    _phy_wc40_firmware_set_helper = trident_wc40_firmware_set;

    return SOC_E_NONE;
}

#define _TD_MMU_MAX_PACKET_BYTES          10240 /* bytes */
#define _TD_MMU_PACKET_HEADER_BYTES       64    /* bytes */
#define _TD_MMU_JUMBO_FRAME_BYTES         9216  /* bytes */
#define _TD_MMU_DEFAULT_MTU_BYTES         1536  /* bytes */

#define _TD_MMU_TOTAL_CELLS               46080 /* 45k cells */

#define _TD_MMU_BYTES_PER_CELL            208   /* bytes (1664 bits) */
#define _TD_MMU_NUM_PG                    8
#define _TD_MMU_NUM_POOL                  4

#define _TD_MMU_BYTES_TO_CELLS(_byte_)  \
    (((_byte_) + _TD_MMU_BYTES_PER_CELL - 1) / _TD_MMU_BYTES_PER_CELL)

/*
 * general syntax: buf.object[id].attribute[.port]="string"
 * Some examples of "cell value" string type:
 *   1000b (b for byte)
 *   1000k (k for kilobyte)
 *   1000m (m for megabyte)
 *   1000c (c for cell)
 *
 * objects     attributes        string type and trident register for reference
 * ========================================================================
 * device
 *            headroom           cell value
 *
 * pool#                         # is pool id
 *            size               cell value or %
 *                               This size will affect both ingress and egress
 *                               pool size, it is recommended to use percentage
 *                               since the total pool size calculate for
 *                               ingress and egress are different.
 *            yellow_size        cell value or %
 *                               If the specified value is percentage, it is
 *                               the percentage of the value specified by the
 *                               size attribute
 *                               Use the same value for size, yellow_size, and
 *                               red_size or use 100% for yellow_size and
 *                               red_size to disable color aware.
 *            red_size           cell value or %
 *                               (see notes for yellow_size)
 *
 * port
 *            guarantee          cell value
 *            pool_limit         cell value
 *            pool_resume        cell value
 *            pkt_size           cell value
 *
 * prigroup#                     # is priority group
 *            guarantee          cell value
 *                               specify 0 to disable
 *            headroom           cell value
 *            device_headroom_enable boolean
 *            port_guarantee_enable boolean
 *            port_max_enable    boolean
 *            pool_scale         floating point number value between 1/64 and 8
 *                               Dynamic method will be enabled if this
 *                               attribute is specified.
 *            pool_limit         cell value
 *            pool_resume        cell value
 *            pool_floor         cell value
 *            flow_control_enable boolean
 *
 * queue#                        # is queue id
 * equeue#                       # is extended queue id
 * mqueue#                       # is multicast queue id
 *            guarantee          cell value
 *            pool_scale         floating point number value between 1/64 and 8
 *                               Dynamic method will be enabled if this
 *                               attribute is specified.
 *            pool_limit         cell value
 *                               Specify 0 to indicate disabling queue limit
 *                               and allow to use shared space.
 *            pool_resume        cell value
 *            yellow_limit       cell value for static or % for dynamic
 *                               Use the same value for pool_limit,
 *                               yellow_limit and red_limit to disable color
 *                               aware.
 *                               Use percentage (such as 12.5%, ... 100%) to
 *                               indicate dynamic color limit
 *            red_limit          cell value for static or % for dynamic
 *                               (see notes for yellow_limit)
 *            yellow_resume      cell value
 *            red_resume         cell value
 *
 * ===== mapping =====
 * general syntax: buf.map.from_object.to_object[.port]="string"
 * string is a command separated value list, use 0 if the value is missing
 * for example:
 *     "a,b,c" has same effect as "a,b,c,0,0,0"
 *     "a,,c" has same effect as "a,0,c"
 *
 * buf.map.pri.prigroup[.port]="a,b,c,..."
 *   a is priority group id for priority 0
 *   b is priority group id for priority 1
 *   ...
 *
 * buf.map.prigroup.pool[.port]="a,b,c,..."
 *   a is service pool id for priority group 0
 *   b is service pool id for priority group 1
 *   ...
 *
 * buf.map.queue.pool[.port]="a,b,c,..."
 * buf.map.mqueue.pool[.port]="a,b,c,..."
 *   a is service pool id for queue 0
 *   b is service pool id for queue 1
 *   ...
 */

#define _TD_BUF_DYNAMIC_FLAG        (0x80000000)
#define _TD_BUF_PERCENT_FLAG        (0x40000000)

typedef struct _soc_trident_buf_prigroup_s {
    int pool_idx; /* from mapping variable */
    int guarantee;
    int headroom;
    int user_delay;
    int switch_delay;
    int pkt_size;
    int device_headroom_enable;
    int port_guarantee_enable;
    int port_max_enable;
    int pool_scale;
    int pool_limit;
    int pool_resume;
    int pool_floor;
    int flow_control_enable;
} _soc_trident_buf_prigroup_t;

typedef struct _soc_trident_buf_queue_s
{
    int pool_idx; /* from mapping variable */
    int guarantee;
    int discard_enable;
    int pool_scale;
    int pool_limit;
    int pool_resume;
    int color_discard_enable;
    int yellow_limit;
    int red_limit;
    int yellow_resume;
    int red_resume;
} _soc_trident_buf_queue_t;

typedef struct _soc_trident_buf_pool_s {
    int size;
    int yellow_size;
    int red_size;
    int total; /* calculated value (not from config variable) */
    int prigroup_guarantee; /* calculated value (not from config variable) */
    int prigroup_headroom; /* calculated value (not from config variable) */
    int queue_guarantee; /* calculated value (not from config variable) */
} _soc_trident_buf_pool_t;

typedef struct _soc_trident_buf_port_s
{
    int guarantee;
    int pool_limit;
    int pool_resume;
    int pkt_size;
    _soc_trident_buf_prigroup_t prigroups[8];
    _soc_trident_buf_queue_t *queues;
    int pri_to_prigroup[16]; /* from mapping variable */
} _soc_trident_buf_port_t;

typedef struct _soc_trident_buf_s
{
    int headroom;
    _soc_trident_buf_pool_t pools[4];
    _soc_trident_buf_port_t ports[66];
    int port_guarantee; /* calculated value (not from config variable) */
} _soc_trident_buf_t;

STATIC void
_soc_trident_property_get(int unit, soc_port_t port, const char *obj,
                          int index, const char *attr, int *setting)
{
    char suffix;

    if (port < 0) {
        *setting = soc_property_obj_attr_get
            (unit, spn_BUF, obj, index, attr, 0, &suffix, *setting);
    } else {
        *setting = soc_property_port_obj_attr_get
            (unit, port, spn_BUF, obj, index, attr, 0, &suffix, *setting);
    }
}

STATIC void
_soc_trident_property_get_cells(int unit, soc_port_t port, const char *obj,
                                int index, const char *attr, int allow_dynamic,
                                int *setting)
{
    int val;
    char suffix;

    /* scale up by 10 during calculation */
    if (*setting & _TD_BUF_DYNAMIC_FLAG) {
        suffix =  '%';
        val = *setting & ~_TD_BUF_DYNAMIC_FLAG;
        val = (val + 1) * 125; /* 0:125 (12.5%), ... 7:1000 (100%) */

    } else {
        suffix = '\0';
        val = *setting * 10;
    }

    if (port < 0) {
        val = soc_property_obj_attr_get
            (unit, spn_BUF, obj, index, attr, 1, &suffix, val);
    } else {
        val = soc_property_port_obj_attr_get
            (unit, port, spn_BUF, obj, index, attr, 1, &suffix, val);
    }

    if (val < 0) { /* treat negative number as zero */
        val = 0;
    }

    /* scale down by 10 after calculation */
    if (allow_dynamic && suffix == '%') {
        val = val > 1000 ? 7 : (val - 1) / 125; /* each unit represent 12.5% */
        val |= _TD_BUF_DYNAMIC_FLAG;
    } else {
        val /= 10;
        switch (suffix) {
        case 'B': /* byte */
        case 'b':
            val = _TD_MMU_BYTES_TO_CELLS(val);
            break;
        case 'K': /* kilobyte */
        case 'k':
            val = _TD_MMU_BYTES_TO_CELLS(val * 1024);
            break;
        case 'M': /* megabyte */
        case 'm':
            val = _TD_MMU_BYTES_TO_CELLS(val * 1048576);
            break;
        default:
            break;
        }
    }

    *setting = val;
}

STATIC void
_soc_trident_property_get_percentage_x100(int unit, soc_port_t port,
                                          const char *obj, int index,
                                          const char *attr, int *setting)
{
    int val;
    char suffix;

    if (*setting & _TD_BUF_PERCENT_FLAG) {
        suffix =  '%';
        val = *setting & ~_TD_BUF_PERCENT_FLAG;
    } else {
        suffix =  '\0';
        val = *setting;
    }

    if (port < 0) {
        val = soc_property_obj_attr_get
            (unit, spn_BUF, obj, index, attr, 2, &suffix, val);
    } else {
        val = soc_property_port_obj_attr_get
            (unit, port, spn_BUF, obj, index, attr, 2, &suffix, val);
    }

    if (suffix == '%') {
        if (val < 0) { /* treat negative number as zero */
            val = 0;
        } else if (val > 10000) { /* treat number larger than 100% as 100% */
            val = 10000;
        }
        *setting = val | _TD_BUF_PERCENT_FLAG;
    } else {
        *setting = val;
    }
}

STATIC void
_soc_trident_property_get_scale(int unit, soc_port_t port,
                                const char *obj, int index,
                                const char *attr, int *setting)
{
    int val, alpha;
    char suffix;

    alpha = 15625;  /* 1/64 = 0.015625, scale up by 1000000 (2**6) */
    val = *setting < 0 ? -1 : alpha << *setting;

    if (port < 0) {
        val = soc_property_obj_attr_get
            (unit, spn_BUF, obj, index, attr, 6, &suffix, val);
    } else {
        val = soc_property_port_obj_attr_get
            (unit, port, spn_BUF, obj, index, attr, 6, &suffix, val);
    }

    if (val < 0) { /* ignore negative number */
        *setting = -1;
    } else {
        for (*setting = 0; *setting < 9; (*setting)++) {
            if (val <= (alpha << *setting)) {
                break;
            }
        }
    }
}

STATIC void
_soc_trident_mmu_config_buf_default(int unit, _soc_trident_buf_t *buf)
{
    soc_info_t *si;
    _soc_trident_buf_pool_t *buf_pool;
    _soc_trident_buf_port_t *buf_port;
    _soc_trident_buf_prigroup_t *buf_prigroup;
    _soc_trident_buf_queue_t *buf_queue;
    int max_packet_cells, jumbo_frame_cells, default_mtu_cells;
    int default_pg_headroom_cells;
    int port, idx, count, num_cosq;

    si = &SOC_INFO(unit);

    max_packet_cells = _TD_MMU_BYTES_TO_CELLS(_TD_MMU_MAX_PACKET_BYTES +
                                              _TD_MMU_PACKET_HEADER_BYTES);
    jumbo_frame_cells = _TD_MMU_BYTES_TO_CELLS(_TD_MMU_JUMBO_FRAME_BYTES +
                                               _TD_MMU_PACKET_HEADER_BYTES);
    default_mtu_cells = _TD_MMU_BYTES_TO_CELLS(_TD_MMU_DEFAULT_MTU_BYTES +
                                               _TD_MMU_PACKET_HEADER_BYTES);
    default_pg_headroom_cells = 160;

    buf->headroom = NUM_PORT(unit) * default_mtu_cells;

    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];

        if (idx == 0) {  /* 100% scale up by 100 */
            buf_pool->size = 10000 | _TD_BUF_PERCENT_FLAG;
            buf_pool->yellow_size = 10000 | _TD_BUF_PERCENT_FLAG;
            buf_pool->red_size = 10000 | _TD_BUF_PERCENT_FLAG;
        } else {
            buf_pool->size = 0;
            buf_pool->yellow_size = 0;
            buf_pool->red_size = 0;
        }
    }

    num_cosq = 0;
    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];

        buf_port->guarantee = jumbo_frame_cells;
        buf_port->pool_limit = _TD_MMU_TOTAL_CELLS;
        buf_port->pool_resume = _TD_MMU_TOTAL_CELLS - default_mtu_cells * 2;
        buf_port->pkt_size = max_packet_cells;

        /* priority group */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf_port->prigroups[idx];

            buf_prigroup->guarantee = 0;
            buf_prigroup->user_delay = -1;
            buf_prigroup->switch_delay = -1;
            buf_prigroup->pkt_size = max_packet_cells;
            buf_prigroup->device_headroom_enable = 1;
            buf_prigroup->pool_limit = 0;
            buf_prigroup->pool_floor = 0;
            if (idx == 7) {
                buf_prigroup->headroom = default_pg_headroom_cells;
                buf_prigroup->port_guarantee_enable = 1;
                buf_prigroup->port_max_enable = 1;
                buf_prigroup->pool_scale = 7;
                buf_prigroup->pool_resume = default_mtu_cells * 2;
                buf_prigroup->flow_control_enable = 1;
            } else {
                buf_prigroup->headroom = 0;
                buf_prigroup->port_guarantee_enable = 0;
                buf_prigroup->port_max_enable = 0;
                buf_prigroup->pool_scale = -1;
                buf_prigroup->pool_resume = 0;
                buf_prigroup->flow_control_enable = 0;
            }
        }

        /* multicast queue */
        count = IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port];
        num_cosq += count;
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf_port->queues[idx];

            buf_queue->guarantee = default_mtu_cells;
            buf_queue->discard_enable = 1;
            buf_queue->pool_scale = 7;
            buf_queue->pool_limit = 0;
            buf_queue->pool_resume = 8;
            buf_queue->color_discard_enable = 0;
            buf_queue->red_limit = 7 | _TD_BUF_DYNAMIC_FLAG;
        }

        /* unicast queue */
        num_cosq += si->port_num_uc_cosq[port];
        for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];

            buf_queue->guarantee = default_mtu_cells;
            buf_queue->discard_enable = 1;
            buf_queue->pool_scale = 7;
            buf_queue->pool_limit = 0;
            buf_queue->pool_resume = 8;
            buf_queue->color_discard_enable = 0;
            buf_queue->yellow_limit = 7 | _TD_BUF_DYNAMIC_FLAG;
            buf_queue->red_limit = 7 | _TD_BUF_DYNAMIC_FLAG;
            buf_queue->yellow_resume = 8;
            buf_queue->red_resume = 8;
        }

        /* extended unicast queue */
        count = SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        num_cosq += count;
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] +
                                          si->port_num_uc_cosq[port] + idx];

            buf_queue->guarantee = default_mtu_cells;
            buf_queue->discard_enable = 1;
            buf_queue->pool_scale = 7;
            buf_queue->pool_limit = 0;
            buf_queue->pool_resume = 8;
            buf_queue->color_discard_enable = 0;
            buf_queue->yellow_limit = 7 | _TD_BUF_DYNAMIC_FLAG;
            buf_queue->red_limit = 6 | _TD_BUF_DYNAMIC_FLAG;
            buf_queue->yellow_resume = 8;
            buf_queue->red_resume = 8;
        }

        /* internal priority to priority group mapping */
        for (idx = 0; idx < 16; idx++) {
            buf_port->pri_to_prigroup[idx] = 7;
        }

        /* priority group to pool mapping */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_port->prigroups[idx].pool_idx = 0;
        }

        /* queue to pool mapping */
        count = si->port_num_cosq[port] + si->port_num_uc_cosq[port] +
            si->port_num_ext_cosq[port];
        for (idx = 0; idx < count; idx++) {
            buf_port->queues[idx].pool_idx = 0;
        }
    }
}

STATIC void
_soc_trident_mmu_config_buf_read(int unit, _soc_trident_buf_t *buf)
{
    soc_info_t *si;
    _soc_trident_buf_pool_t *buf_pool;
    _soc_trident_buf_port_t *buf_port;
    _soc_trident_buf_prigroup_t *buf_prigroup;
    _soc_trident_buf_queue_t *buf_queue;
    int port, idx, count;
    char name[80];
    int values[64];

    si = &SOC_INFO(unit);

    _soc_trident_property_get_cells
        (unit, -1, spn_DEVICE, -1, spn_HEADROOM, FALSE, &buf->headroom);

    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];

        _soc_trident_property_get_percentage_x100
            (unit, -1, spn_POOL, idx, spn_SIZE, &buf_pool->size);

        _soc_trident_property_get_percentage_x100
            (unit, -1, spn_POOL, idx, spn_YELLOW_SIZE, &buf_pool->yellow_size);

        _soc_trident_property_get_percentage_x100
            (unit, -1, spn_POOL, idx, spn_RED_SIZE, &buf_pool->red_size);
    }

    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];

        _soc_trident_property_get_cells
            (unit, port, spn_PORT, -1, spn_GUARANTEE, FALSE,
             &buf_port->guarantee);

        _soc_trident_property_get_cells
            (unit, port, spn_PORT, -1, spn_POOL_LIMIT, FALSE,
             &buf_port->pool_limit);

        _soc_trident_property_get_cells
            (unit, port, spn_PORT, -1, spn_POOL_RESUME, FALSE,
             &buf_port->pool_resume);

        _soc_trident_property_get_cells
            (unit, port, spn_PORT, -1, spn_PKT_SIZE, FALSE,
             &buf_port->pkt_size);

        /* priority group */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf_port->prigroups[idx];

            _soc_trident_property_get_cells
                (unit, port, spn_PRIGROUP, idx, spn_GUARANTEE, FALSE,
                 &buf_prigroup->guarantee);

            _soc_trident_property_get_cells
                (unit, port, spn_PRIGROUP, idx, spn_HEADROOM, FALSE,
                 &buf_prigroup->headroom);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_USER_DELAY,
                 &buf_prigroup->user_delay);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_SWITCH_DELAY,
                 &buf_prigroup->switch_delay);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_PKT_SIZE,
                 &buf_prigroup->pkt_size);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_DEVICE_HEADROOM_ENABLE,
                 &buf_prigroup->device_headroom_enable);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_PORT_GUARANTEE_ENABLE,
                 &buf_prigroup->port_guarantee_enable);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_PORT_MAX_ENABLE,
                 &buf_prigroup->port_max_enable);

            _soc_trident_property_get_scale
                (unit, port, spn_PRIGROUP, idx, spn_POOL_SCALE,
                 &buf_prigroup->pool_scale);

            _soc_trident_property_get_cells
                (unit, port, spn_PRIGROUP, idx, spn_POOL_LIMIT, FALSE,
                 &buf_prigroup->pool_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_PRIGROUP, idx, spn_POOL_RESUME, FALSE,
                 &buf_prigroup->pool_resume);

            _soc_trident_property_get_cells
                (unit, port, spn_PRIGROUP, idx, spn_POOL_FLOOR, FALSE,
                 &buf_prigroup->pool_floor);

            _soc_trident_property_get
                (unit, port, spn_PRIGROUP, idx, spn_FLOW_CONTROL_ENABLE,
                 &buf_prigroup->flow_control_enable);
        }

        /* multicast queue */
        count = IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port];
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf_port->queues[idx];

            _soc_trident_property_get_cells
                (unit, port, spn_MQUEUE, idx, spn_GUARANTEE, FALSE,
                 &buf_queue->guarantee);

            _soc_trident_property_get
                (unit, port, spn_MQUEUE, idx, spn_DISCARD_ENABLE,
                 &buf_queue->discard_enable);

            _soc_trident_property_get_scale
                (unit, port, spn_MQUEUE, idx, spn_POOL_SCALE,
                 &buf_queue->pool_scale);

            _soc_trident_property_get_cells
                (unit, port, spn_MQUEUE, idx, spn_POOL_LIMIT, FALSE,
                 &buf_queue->pool_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_MQUEUE, idx, spn_POOL_RESUME, FALSE,
                 &buf_queue->pool_resume);

            _soc_trident_property_get
                (unit, port, spn_MQUEUE, idx, spn_COLOR_DISCARD_ENABLE,
                 &buf_queue->color_discard_enable);

            _soc_trident_property_get_cells
                (unit, port, spn_MQUEUE, idx, spn_RED_LIMIT, TRUE,
                 &buf_queue->red_limit);
        }

        /* unicast queue */
        for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE,
                 &buf_queue->guarantee);

            _soc_trident_property_get
                (unit, port, spn_QUEUE, idx, spn_DISCARD_ENABLE,
                 &buf_queue->discard_enable);

            _soc_trident_property_get_scale
                (unit, port, spn_QUEUE, idx, spn_POOL_SCALE,
                 &buf_queue->pool_scale);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_POOL_LIMIT, FALSE,
                 &buf_queue->pool_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_POOL_RESUME, FALSE,
                 &buf_queue->pool_resume);

            _soc_trident_property_get
                (unit, port, spn_QUEUE, idx, spn_COLOR_DISCARD_ENABLE,
                 &buf_queue->color_discard_enable);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_YELLOW_LIMIT, TRUE,
                 &buf_queue->yellow_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_RED_LIMIT, TRUE,
                 &buf_queue->red_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_YELLOW_RESUME, FALSE,
                 &buf_queue->yellow_resume);

            _soc_trident_property_get_cells
                (unit, port, spn_QUEUE, idx, spn_RED_RESUME, FALSE,
                 &buf_queue->red_resume);
        }

        /* extended unicast queue */
        count = SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] +
                                          si->port_num_uc_cosq[port] + idx];

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_GUARANTEE, FALSE,
                 &buf_queue->guarantee);

            _soc_trident_property_get
                (unit, port, spn_EQUEUE, idx, spn_DISCARD_ENABLE,
                 &buf_queue->discard_enable);

            _soc_trident_property_get_scale
                (unit, port, spn_EQUEUE, idx, spn_POOL_SCALE,
                 &buf_queue->pool_scale);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_POOL_LIMIT, FALSE,
                 &buf_queue->pool_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_POOL_RESUME, FALSE,
                 &buf_queue->pool_resume);

            _soc_trident_property_get
                (unit, port, spn_EQUEUE, idx, spn_COLOR_DISCARD_ENABLE,
                 &buf_queue->color_discard_enable);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_YELLOW_LIMIT, TRUE,
                 &buf_queue->yellow_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_RED_LIMIT, TRUE,
                 &buf_queue->red_limit);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_YELLOW_RESUME, FALSE,
                 &buf_queue->yellow_resume);

            _soc_trident_property_get_cells
                (unit, port, spn_EQUEUE, idx, spn_RED_RESUME, FALSE,
                 &buf_queue->red_resume);
        }

        /* internal priority to priority group mapping */
        sal_sprintf(name, "%s.%s.%s.%s",
                    spn_BUF, spn_MAP, spn_PRI, spn_PRIGROUP);
        (void)soc_property_port_get_csv(unit, port, name, 16,
                                        buf_port->pri_to_prigroup);

        /* priority group to pool mapping */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            values[idx] = buf_port->prigroups[idx].pool_idx;
        }
        sal_sprintf(name, "%s.%s.%s.%s",
                    spn_BUF, spn_MAP, spn_PRIGROUP, spn_POOL);
        count = soc_property_port_get_csv(unit, port, name, _TD_MMU_NUM_PG,
                                          values);
        for (idx = 0; idx < count; idx++) {
            buf_port->prigroups[idx].pool_idx = values[idx];
        }

        /* multicast queue to pool mapping */
        count = IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port];
        buf_queue = &buf_port->queues[0];
        for (idx = 0; idx < count; idx++) {
            values[idx] = buf_queue[idx].pool_idx;
        }
        sal_sprintf(name, "%s.%s.%s.%s",
                    spn_BUF, spn_MAP, spn_MQUEUE, spn_POOL);
        count = soc_property_port_get_csv(unit, port, name, count, values);
        for (idx = 0; idx < count; idx++) {
            buf_queue[idx].pool_idx = values[idx];
        }

        /* regular unicast queue to pool mapping */
        count = si->port_num_uc_cosq[port];
        if (count > 0) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port]];
            for (idx = 0; idx < count; idx++) {
                values[idx] = buf_queue[idx].pool_idx;
            }
            sal_sprintf(name, "%s.%s.%s.%s",
                        spn_BUF, spn_MAP, spn_QUEUE, spn_POOL);
            (void)soc_property_port_get_csv(unit, port, name, count, values);
            for (idx = 0; idx < count; idx++) {
                buf_queue[idx].pool_idx = values[idx];
            }
        }

        /* extended unicast queue to pool mapping */
        count = SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        if (count > 0) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] +
                                          si->port_num_uc_cosq[port]];
            for (idx = 0; idx < count; idx++) {
                values[idx] = buf_queue[idx].pool_idx;
            }
            sal_sprintf(name, "%s.%s.%s.%s",
                        spn_BUF, spn_MAP, spn_EQUEUE, spn_POOL);
            (void)soc_property_port_get_csv(unit, port, name, count, values);
            for (idx = 0; idx < count; idx++) {
                buf_queue[idx].pool_idx = values[idx];
            }
        }
    }
}

STATIC void
_soc_trident_mmu_config_buf_calculate(int unit, _soc_trident_buf_t *buf)
{
    soc_info_t *si;
    _soc_trident_buf_pool_t *buf_pool;
    _soc_trident_buf_port_t *buf_port;
    _soc_trident_buf_prigroup_t *buf_prigroup;
    _soc_trident_buf_queue_t *buf_queue;
    int port, idx, count;

    si = &SOC_INFO(unit);

    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf_port->prigroups[idx];
            if (buf_prigroup->user_delay != -1 &&
                buf_prigroup->switch_delay != -1) {
                /*
                 * number of max leftever cells =
                 *   port speed (megabits per sec) * 10**6 (megabits to bit) *
                 *   delay (nsec) / 10**9 (nsecs to second) /
                 *   8 (bits per byte) /
                 *   (IPG (12 bytes) + preamble (8 bytes) +
                 *    worse case packet size (145 bytes)) *
                 *   worse case packet size (2 cells)
                 * heandroom =
                 *   mtu (cells) + number of leftover cells
                 */
                buf_prigroup->headroom = buf_prigroup->pkt_size +
                    si->port_speed_max[port] *
                    (buf_prigroup->user_delay + buf_prigroup->switch_delay) *
                    2 / (8 * (12 + 8 + 145) * 1000);
            }
        }
    }

    /*
     * Input port pool allocation precedence:
     *   reserved space: per port per priority group minimum space
     *   reserved space: per port minimum space (include cpu port)
     *   shared space = total - input port reserved - output port reserved
     *   reserved space: per port per priority group headroom
     *   reserved space: device global headroom
     * Output port:
     *   reserved space: per port per queue minimum space
     *   shared space = total - output port reserved
     *
     * Total memory space equals to
     *     total cells
     *     minus (#1) device global headroom
     * Per pool memory space qeuals to
     *     total memory space * percentage
     * Per pool shared limit equals to
     *     Per pool memory space
     *     minus (#2) input port minimum space (include cpu port)
     *     minus (#3) input port per priority group minimum space (in the pool)
     *     minus (#4) input port per priority group headroom (in the pool)
     *     minus (#5) output port per queue minimum space (in the pool)
     */

    buf->port_guarantee = 0;
    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];
        buf->port_guarantee += buf_port->guarantee; /* #2 */
    }

    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];
        buf_pool->prigroup_guarantee = 0;
        buf_pool->prigroup_headroom = 0;
        buf_pool->queue_guarantee = 0;
        if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
            continue;
        }

        if (buf_pool->size & _TD_BUF_PERCENT_FLAG) {
            buf_pool->total = (buf_pool->size & ~_TD_BUF_PERCENT_FLAG) *
                (_TD_MMU_TOTAL_CELLS - buf->headroom) / 10000; /* #1 */
        }
        buf_pool->total -= buf->port_guarantee;
    }

    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf_port->prigroups[idx];
            buf_pool = &buf->pools[buf_prigroup->pool_idx];
            buf_pool->prigroup_guarantee += buf_prigroup->guarantee; /* #3 */
            buf_pool->prigroup_headroom += buf_prigroup->headroom; /* #4 */
        }
        count = (IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port]) +
            si->port_num_uc_cosq[port];
        count += SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf_port->queues[idx];
            buf_pool = &buf->pools[buf_queue->pool_idx];
            buf_pool->queue_guarantee += buf_queue->guarantee; /* #5 */
        }
    }

    if (soc_cm_debug_check(DK_VERBOSE)) {
        soc_cm_print("MMU buffer usage:\n");
        soc_cm_print("  Global headroom: %d\n", buf->headroom);
        soc_cm_print("  Total port guarantee: %d\n", buf->port_guarantee);
        for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
            buf_pool = &buf->pools[idx];
            if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
                continue;
            }
            soc_cm_print("  Pool %d total prigroup guarantee: %d\n",
                         idx, buf_pool->prigroup_guarantee);
            soc_cm_print("  Pool %d total prigroup headroom: %d\n",
                         idx, buf_pool->prigroup_headroom);
            soc_cm_print("  Pool %d total queue guarantee: %d\n",
                         idx, buf_pool->queue_guarantee);
        }
    }
}

int
_soc_trident_mmu_config_buf_check(int unit, _soc_trident_buf_t *buf)
{
    soc_info_t *si;
    _soc_trident_buf_pool_t *buf_pool;
    _soc_trident_buf_port_t *buf_port;
    _soc_trident_buf_prigroup_t *buf_prigroup;
    _soc_trident_buf_queue_t *buf_queue;
    int yellow_cells, red_cells;
    int port, dft_pool, idx, queue_idx, count;
    uint32 pool_map;
    char queue_name[10];

    si = &SOC_INFO(unit);

    _soc_trident_mmu_config_buf_calculate(unit, buf);

    count = 0;
    dft_pool =0;
    pool_map = 0;
    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];
        if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
            continue;
        }

        if (buf_pool->total <=
            buf_pool->prigroup_guarantee + buf_pool->prigroup_headroom +
            buf_pool->queue_guarantee) {
            soc_cm_print("MMU config: Pool %d memory space size is zero\n",
                         idx);
            return SOC_E_FAIL;
        }

        if (pool_map == 0) {
            dft_pool = idx;
        }
        pool_map |= 1 << idx;

        count += buf_pool->total + buf->port_guarantee;

        if (buf_pool->yellow_size & _TD_BUF_PERCENT_FLAG) {
            yellow_cells = (buf_pool->yellow_size & ~_TD_BUF_PERCENT_FLAG) *
                buf_pool->total / 10000;
        } else {
            yellow_cells = buf_pool->yellow_size;
        }
        if (buf_pool->red_size & _TD_BUF_PERCENT_FLAG) {
            red_cells = (buf_pool->red_size & ~_TD_BUF_PERCENT_FLAG) *
                buf_pool->total / 10000;
        } else {
            red_cells = buf_pool->red_size;
        }

        if (yellow_cells > red_cells) {
            soc_cm_print("MMU config pool %d: Yellow cells offset is higher "
                         "than red cells\n", idx);
        }
        if (red_cells > buf_pool->total) {
            soc_cm_print("MMU config pool %d: Red cells offset is higher "
                         "than pool shared cells\n", idx);
        }
    }
    if (count > _TD_MMU_TOTAL_CELLS - buf->headroom) {
        soc_cm_print("MMU config: The summary of pool shared cells is more "
                     "than total shared cells available\n");
    }

    

    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];

        /* internal priority to priority group mapping */
        for (idx = 0; idx < 16; idx++) {
            if (buf_port->pri_to_prigroup[idx] < 0 ||
                buf_port->pri_to_prigroup[idx] >= _TD_MMU_NUM_PG) {
                soc_cm_print("MMU config port %d: Invalid prigroup value (%d) "
                             "for internal priority %d\n",
                             port, buf_port->pri_to_prigroup[idx], idx);
                buf_port->pri_to_prigroup[idx] = 0; /* use prigroup 0 */
            }
        }

        /* priority group to pool mapping */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf_port->prigroups[idx];
            if (buf_prigroup->pool_idx < 0 ||
                buf_prigroup->pool_idx >= _TD_MMU_NUM_POOL) {
                soc_cm_print("MMU config port %d prigroup %d: "
                             "Invalid pool value (%d)\n",
                             port, idx, buf_prigroup->pool_idx);
                /* use first non-empty pool */
                buf_prigroup->pool_idx = dft_pool;
            } else if (!(pool_map & (1 << buf_prigroup->pool_idx))) {
                soc_cm_print("MMU config port %d prigroup %d: "
                             "Pool %d is empty\n",
                             port, idx, buf_prigroup->pool_idx);
            }
        }

        /* queue to pool mapping */
        count = (IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port]) +
            si->port_num_uc_cosq[port];
        count += SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf->ports[port].queues[idx];

            queue_idx = idx;
            if (queue_idx < si->port_num_cosq[port]) {
                sal_sprintf(queue_name, "mqueue %d", queue_idx);
            } else {
                queue_idx -= si->port_num_cosq[port];
                if (queue_idx < si->port_num_uc_cosq[port]) {
                    sal_sprintf(queue_name, "queue %d", queue_idx);
                } else {
                    queue_idx -= si->port_num_uc_cosq[port];
                    sal_sprintf(queue_name, "equeue %d", queue_idx);
                }
            }

            if (buf_queue->pool_idx < 0 ||
                buf_queue->pool_idx >= _TD_MMU_NUM_POOL) {
                soc_cm_print("MMU config port %d %s: "
                             "Invalid pool value (%d)\n",
                             port, queue_name, buf_queue->pool_idx);
                buf_queue->pool_idx = dft_pool; /* use first non-empty pool */
            } else if (!(pool_map & (1 << buf_queue->pool_idx))) {
                soc_cm_print("MMU config port %d %s: Pool %d is empty\n",
                             port, queue_name, buf_queue->pool_idx);
            }
        }
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_mmu_config_buf_set_hw(int unit, _soc_trident_buf_t *buf)
{
    soc_info_t *si;
    _soc_trident_buf_pool_t *buf_pool;
    _soc_trident_buf_port_t *buf_port;
    _soc_trident_buf_prigroup_t *buf_prigroup;
    _soc_trident_buf_queue_t *buf_queue;
    soc_reg_t reg = INVALIDr;
    soc_mem_t config_mem, offset_mem;
    uint32 rval, fval;
    uint32 entry0[SOC_MAX_MEM_WORDS], entry1[SOC_MAX_MEM_WORDS];
    int default_mtu_cells, limit;
    int port, phy_port, mmu_port, base, idx, count;
    static const soc_field_t prigroup_reg[] = {
        PORT_PRI_GRP0r, PORT_PRI_GRP1r
    };
    static const soc_field_t prigroup_field[] = {
        PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
        PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
        PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
        PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
    };
    static const soc_field_t prigroup_spid_field[] = {
        PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
        PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
    };
    static const soc_field_t uc_spid_field[] = {
        COS0_SPIDf, COS1_SPIDf, COS2_SPIDf, COS3_SPIDf,
        COS4_SPIDf, COS5_SPIDf, COS6_SPIDf, COS7_SPIDf,
        COS8_SPIDf, COS9_SPIDf
    };
    static const soc_field_t ext_spid_reg[] = {
        OP_EX_PORT_CONFIG_SPID_0r, OP_EX_PORT_CONFIG_SPID_1r,
        OP_EX_PORT_CONFIG_SPID_2r, OP_EX_PORT_CONFIG_SPID_3r,
        OP_EX_PORT_CONFIG_SPID_4r
    };
    static const soc_field_t ext_spid_field[] = {
        Q0_SPIDf, Q1_SPIDf, Q2_SPIDf, Q3_SPIDf,
        Q4_SPIDf, Q5_SPIDf, Q6_SPIDf, Q7_SPIDf,
        Q8_SPIDf, Q9_SPIDf, Q10_SPIDf, Q11_SPIDf,
        Q12_SPIDf, Q13_SPIDf, Q14_SPIDf, Q15_SPIDf,
        Q16_SPIDf, Q17_SPIDf, Q18_SPIDf, Q19_SPIDf,
        Q20_SPIDf, Q21_SPIDf, Q22_SPIDf, Q23_SPIDf,
        Q24_SPIDf, Q25_SPIDf, Q26_SPIDf, Q27_SPIDf,
        Q28_SPIDf, Q29_SPIDf, Q30_SPIDf, Q31_SPIDf,
        Q32_SPIDf, Q33_SPIDf, Q34_SPIDf, Q35_SPIDf,
        Q36_SPIDf, Q37_SPIDf, Q38_SPIDf, Q39_SPIDf,
        Q40_SPIDf, Q41_SPIDf, Q42_SPIDf, Q43_SPIDf,
        Q44_SPIDf, Q45_SPIDf, Q46_SPIDf, Q47_SPIDf,
        Q48_SPIDf, Q49_SPIDf, Q50_SPIDf, Q51_SPIDf,
        Q52_SPIDf, Q53_SPIDf, Q54_SPIDf, Q55_SPIDf,
        Q56_SPIDf, Q57_SPIDf, Q58_SPIDf, Q59_SPIDf,
        Q60_SPIDf, Q61_SPIDf, Q62_SPIDf, Q63_SPIDf,
        Q64_SPIDf, Q65_SPIDf, Q66_SPIDf, Q67_SPIDf,
        Q68_SPIDf, Q69_SPIDf, Q70_SPIDf, Q71_SPIDf,
        Q72_SPIDf, Q73_SPIDf
    };

    si = &SOC_INFO(unit);

    default_mtu_cells = _TD_MMU_BYTES_TO_CELLS(_TD_MMU_DEFAULT_MTU_BYTES +
                                               _TD_MMU_PACKET_HEADER_BYTES);

    /* internal priority to priority group mapping */
    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];

        for (idx = 0; idx < 16; idx++) {
            if (idx % 8 == 0) { /* 8 fields per register */
                reg = prigroup_reg[idx / 8];
                rval = 0;
            }
            soc_reg_field_set(unit, reg, &rval, prigroup_field[idx],
                              buf_port->pri_to_prigroup[idx]);
            if (idx % 8 == 7) { /* 8 fields per register */
                SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
            }
        }
    }

    /* Input port device settings */
    rval = 0;
    soc_reg_field_set(unit, GLOBAL_HDRM_LIMITr, &rval, GLOBAL_HDRM_LIMITf,
                      buf->headroom);
    SOC_IF_ERROR_RETURN(WRITE_GLOBAL_HDRM_LIMITr(unit, rval));

    fval = 0;
    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        if ((buf->pools[idx].size & ~_TD_BUF_PERCENT_FLAG) != 0) {
            fval |= 1 << idx;
        }
    }
    rval = 0;
    soc_reg_field_set(unit, USE_SP_SHAREDr, &rval, ENABLEf, fval);
    SOC_IF_ERROR_RETURN(WRITE_USE_SP_SHAREDr(unit, rval));

    fval = 0;
    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];
        if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
            continue;
        }

        if (buf_pool->yellow_size & _TD_BUF_PERCENT_FLAG) {
            if ((buf_pool->yellow_size & ~_TD_BUF_PERCENT_FLAG) < 10000) {
                fval |= 1 << idx;
            }
        } else {
            if (buf->pools[idx].size != buf->pools[idx].yellow_size) {
                fval |= 1 << idx;
            }
        }
    }
    rval = 0;
    soc_reg_field_set(unit, COLOR_AWAREr, &rval, ENABLEf, fval);
    SOC_IF_ERROR_RETURN(WRITE_COLOR_AWAREr(unit, rval));

    /* Input port per service pool settings */
    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];
        if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
            continue;
        }

        limit = buf_pool->total - buf_pool->prigroup_guarantee -
            buf_pool->prigroup_headroom - buf_pool->queue_guarantee;

        rval = 0;
        soc_reg_field_set(unit, BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, limit);
        SOC_IF_ERROR_RETURN(WRITE_BUFFER_CELL_LIMIT_SPr(unit, idx, rval));

        rval = 0;
        soc_reg_field_set(unit, CELL_RESET_LIMIT_OFFSET_SPr, &rval, OFFSETf,
                          NUM_PORT(unit) * default_mtu_cells / 2);
        SOC_IF_ERROR_RETURN
            (WRITE_CELL_RESET_LIMIT_OFFSET_SPr(unit, idx, rval));

        if (buf_pool->yellow_size & _TD_BUF_PERCENT_FLAG) {
            if ((buf_pool->yellow_size & ~_TD_BUF_PERCENT_FLAG) == 10000) {
                continue;
            }
        } else {
            if (buf->pools[idx].size == buf->pools[idx].yellow_size) {
                continue;
            }
        }

        if (buf_pool->yellow_size & _TD_BUF_PERCENT_FLAG) {
            fval = (buf_pool->yellow_size & ~_TD_BUF_PERCENT_FLAG) * limit /
                10000;
        } else {
            fval = buf_pool->yellow_size;
        }
        rval = 0;
        soc_reg_field_set(unit, CELL_SPAP_YELLOW_OFFSET_SPr, &rval, OFFSETf,
                          fval);
        SOC_IF_ERROR_RETURN
            (WRITE_CELL_SPAP_YELLOW_OFFSET_SPr(unit, idx, rval));

        if (buf_pool->red_size & _TD_BUF_PERCENT_FLAG) {
            fval = (buf_pool->red_size & ~_TD_BUF_PERCENT_FLAG) * limit /
                10000;
        } else {
            fval = buf_pool->red_size;
        }
        rval = 0;
        soc_reg_field_set(unit, CELL_SPAP_RED_OFFSET_SPr, &rval, OFFSETf,
                          fval);
        SOC_IF_ERROR_RETURN(WRITE_CELL_SPAP_RED_OFFSET_SPr(unit, idx, rval));
    }

    /* Input port per port settings */
    PBMP_ALL_ITER(unit, port) {
        buf_port = &buf->ports[port];

        rval = 0;
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            soc_reg_field_set(unit, PORT_PG_SPIDr, &rval,
                              prigroup_spid_field[idx],
                              buf_port->prigroups[idx].pool_idx);
        }
        SOC_IF_ERROR_RETURN(WRITE_PORT_PG_SPIDr(unit, port, rval));

        rval = 0;
        soc_reg_field_set(unit, PORT_MIN_CELLr, &rval, PORT_MINf,
                          buf_port->guarantee);
        SOC_IF_ERROR_RETURN(WRITE_PORT_MIN_CELLr(unit, port, rval));

        rval = 0;
        soc_reg_field_set(unit, PORT_MAX_SHARED_CELLr, &rval, PORT_MAXf,
                          buf_port->pool_limit);
        SOC_IF_ERROR_RETURN(WRITE_PORT_MAX_SHARED_CELLr(unit, port, rval));

        rval = 0;
        soc_reg_field_set(unit, PORT_RESUME_LIMIT_CELLr, &rval, CELLSf,
                          buf_port->pool_resume);
        SOC_IF_ERROR_RETURN(WRITE_PORT_RESUME_LIMIT_CELLr(unit, port, rval));

        fval = 0;
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            if (buf_port->prigroups[idx].port_guarantee_enable != 0) {
                fval |= 1 << idx;
            }
        }
        rval = 0;
        soc_reg_field_set(unit, PORT_MIN_PG_ENABLEr, &rval, PG_BMPf, fval);
        SOC_IF_ERROR_RETURN(WRITE_PORT_MIN_PG_ENABLEr(unit, port, rval));

        fval = 0;
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            if (buf_port->prigroups[idx].port_max_enable != 0) {
                fval |= 1 << idx;
            }
        }
        rval = 0;
        soc_reg_field_set(unit, PORT_SHARED_MAX_PG_ENABLEr, &rval, PG_BMPf,
                          fval);
        SOC_IF_ERROR_RETURN
            (WRITE_PORT_SHARED_MAX_PG_ENABLEr(unit, port, rval));

        fval = 0;
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            if (buf_port->prigroups[idx].flow_control_enable != 0) {
                fval |= 1 << idx;
            }
        }
        rval = 0;
        soc_reg_field_set(unit, PORT_PRI_XON_ENABLEr, &rval,
                          PORT_PRI_XON_ENABLEf, fval);
        SOC_IF_ERROR_RETURN(WRITE_PORT_PRI_XON_ENABLEr(unit, port, rval));

        rval = 0;
        soc_reg_field_set(unit, PORT_MAX_PKT_SIZEr, &rval, PORT_MAX_PKT_SIZEf,
                          buf_port->pkt_size);
        SOC_IF_ERROR_RETURN(WRITE_PORT_MAX_PKT_SIZEr(unit, port, rval));

        /* Input port per port per priority group settings */
        for (idx = 0; idx < _TD_MMU_NUM_PG; idx++) {
            buf_prigroup = &buf->ports[port].prigroups[idx];

            rval = 0;
            soc_reg_field_set(unit, PG_MIN_CELLr, &rval, PG_MINf,
                              buf_prigroup->guarantee);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, PG_MIN_CELLr, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, PG_HDRM_LIMIT_CELLr, &rval, PG_GEf,
                              buf_prigroup->device_headroom_enable);
            soc_reg_field_set(unit, PG_HDRM_LIMIT_CELLr, &rval, PG_HDRM_LIMITf,
                              buf_prigroup->headroom);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, PG_HDRM_LIMIT_CELLr, port, idx, rval));

            rval = 0;
            if (buf_prigroup->pool_scale != -1) {
                soc_reg_field_set(unit, PG_SHARED_LIMIT_CELLr, &rval,
                                  PG_SHARED_DYNAMICf, 1);
                soc_reg_field_set(unit, PG_SHARED_LIMIT_CELLr, &rval,
                                  PG_SHARED_LIMITf, buf_prigroup->pool_scale);
            } else {
                /* PG_SHARED_DYNAMICf is 0 */
                soc_reg_field_set(unit, PG_SHARED_LIMIT_CELLr, &rval,
                                  PG_SHARED_LIMITf, buf_prigroup->pool_limit);
            }
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, PG_SHARED_LIMIT_CELLr, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, PG_RESET_OFFSET_CELLr, &rval,
                              PG_RESET_OFFSETf, buf_prigroup->pool_resume);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, PG_RESET_OFFSET_CELLr, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, PG_RESET_FLOOR_CELLr, &rval,
                              PG_RESET_FLOORf, buf_prigroup->pool_floor);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, PG_RESET_FLOOR_CELLr, port, idx, rval));
        }
    }

    /* Output port per port per queue setting for multicast queue */
    PBMP_ALL_ITER(unit, port) {
        count = IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port];
        for (idx = 0; idx < count; idx++) {
            buf_queue = &buf->ports[port].queues[idx];

            rval = 0;
            soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_MIN_CELLf,
                              buf_queue->guarantee);
            if (buf_queue->pool_scale != -1) {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
                                  Q_SHARED_ALPHA_CELLf,
                                  buf_queue->pool_scale);
            } else {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
                                  Q_SHARED_LIMIT_CELLf,
                                  buf_queue->pool_limit);
            }
            SOC_IF_ERROR_RETURN
                (WRITE_OP_QUEUE_CONFIG_CELLr(unit, port, idx, rval));

            rval = 0;
            if (buf_queue->discard_enable) {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
                                  Q_LIMIT_ENABLE_CELLf, 1);
            }
            if (buf_queue->pool_scale != -1) {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
                                  Q_LIMIT_DYNAMIC_CELLf, 1);
            }
            if (buf_queue->color_discard_enable) {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
                                  Q_COLOR_ENABLE_CELLf, 1);
            }
            if (buf_queue->red_limit & _TD_BUF_DYNAMIC_FLAG) {
                soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
                                  Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
            }
            soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
                              Q_SPIDf, buf_queue->pool_idx);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, OP_QUEUE_LIMIT_COLOR_CELLr, &rval, REDf,
                              buf_queue->red_limit & ~_TD_BUF_DYNAMIC_FLAG);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_QUEUE_LIMIT_COLOR_CELLr(unit, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, OP_QUEUE_RESET_OFFSET_CELLr, &rval,
                              Q_RESET_OFFSET_CELLf,
                              buf_queue->pool_resume / 8);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_QUEUE_RESET_OFFSET_CELLr(unit, port, idx, rval));
        }
    }

    /* Output port per port per queue setting for regular unicast queue */
    PBMP_PORT_ITER(unit, port) {
        phy_port = si->port_l2p_mapping[port];
        mmu_port = si->port_p2m_mapping[phy_port];
        if (si->port_num_ext_cosq[port] == 0) {
            if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
                config_mem = MMU_THDO_CONFIG_0m;
                offset_mem = MMU_THDO_OFFSET_0m;
                /* Index starts from mmu port 5, 10 entries per port */
                base = (mmu_port - 5) * 10;
            } else { /* Y pipe */
                config_mem = MMU_THDO_CONFIG_1m;
                offset_mem = MMU_THDO_OFFSET_1m;
                /* Index starts from mmu port 38, 10 entries per port */
                base = (mmu_port - 38) * 10;
            }
        } else {
            /*
             * Depends on OP_VOQ_PORT_CONFIG mode setting for the extended
             * queue port:
             * - cos mode
             *     use MMU_THDO_CONFIG_SP_x table, 10 entries per port
             * - queue mode
             *     use MMU_THDO_CONFIG_EX_x table, 74 entries per port
             *     extended unicast queues: index 0-63
             *     regular unicast queue: index 64-73
             */
            if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
                config_mem = MMU_THDO_CONFIG_EX_0m;
                offset_mem = MMU_THDO_OFFSET_EX_0m;
                /* Index starts from mmu port 1, 74 entries per port */
                base = (mmu_port - 1) * 74 + 64;
            } else { /* Y pipe */
                config_mem = MMU_THDO_CONFIG_EX_1m;
                offset_mem = MMU_THDO_OFFSET_EX_1m;
                /* Index starts from mmu port 34, 74 entries per port */
                base = (mmu_port - 34) * 74 + 64;
            }
        }
        for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
            buf_queue = &buf->ports[port].queues
                [si->port_num_cosq[port] + idx];

            sal_memset(entry0, 0, sizeof(mmu_thdo_config_0_entry_t));
            sal_memset(entry1, 0, sizeof(mmu_thdo_offset_0_entry_t));

            soc_mem_field32_set(unit, config_mem, entry0, Q_MIN_CELLf,
                                buf_queue->guarantee);
            if (buf_queue->discard_enable) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_LIMIT_ENABLE_CELLf, 1);
            }
            if (buf_queue->pool_scale != -1) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_LIMIT_DYNAMIC_CELLf, 1);
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_SHARED_ALPHA_CELLf,
                                    buf_queue->pool_scale);
            } else {
                /* Q_LIMIT_DYNAMIC_CELLf is 0 */
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_SHARED_LIMIT_CELLf,
                                    buf_queue->pool_limit);
            }
            soc_mem_field32_set(unit, offset_mem, entry1, RESET_OFFSET_CELLf,
                                buf_queue->pool_resume / 8);
            if (buf_queue->color_discard_enable) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_COLOR_ENABLE_CELLf, fval);
            }
            if (buf_queue->yellow_limit & _TD_BUF_DYNAMIC_FLAG) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
                soc_mem_field32_set
                    (unit, config_mem, entry0, LIMIT_YELLOW_CELLf,
                     buf_queue->yellow_limit & ~_TD_BUF_DYNAMIC_FLAG);
                soc_mem_field32_set
                    (unit, offset_mem, entry1, LIMIT_RED_CELLf,
                     buf_queue->red_limit & ~_TD_BUF_DYNAMIC_FLAG);
            } else {
                /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
                soc_mem_field32_set
                    (unit, config_mem, entry0, LIMIT_YELLOW_CELLf,
                     buf_queue->yellow_limit / 8);
                soc_mem_field32_set
                    (unit, offset_mem, entry1, LIMIT_RED_CELLf,
                     buf_queue->red_limit / 8);
            }
            soc_mem_field32_set
                (unit, offset_mem, entry1, RESET_OFFSET_YELLOW_CELLf,
                 buf_queue->yellow_resume / 8);
            soc_mem_field32_set
                (unit, offset_mem, entry1, RESET_OFFSET_RED_CELLf,
                 buf_queue->red_resume / 8);
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL,
                               base + idx, entry0));
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL,
                               base + idx, entry1));
        }
    }

    /* Output port per port per queue setting for extended unicast queue */
    SOC_PBMP_ITER(si->eq_pbm, port) {
        /* coverity[overrun-local : FALSE] */
        phy_port = si->port_l2p_mapping[port];
        mmu_port = si->port_p2m_mapping[phy_port];

        /*
         * 74 entries per port:
         *     extended unicast queues: index 0-63
         *     regular unicast queue: index 64-73 (when in queue mode)
         */
        if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
            config_mem = MMU_THDO_CONFIG_EX_0m;
            offset_mem = MMU_THDO_OFFSET_EX_0m;
            /* Index starts from mmu port 1, 74 entries per port */
            base = (mmu_port - 1) * 74;
        } else { /* Y pipe */
            config_mem = MMU_THDO_CONFIG_EX_1m;
            offset_mem = MMU_THDO_OFFSET_EX_1m;
            /* Index starts from mmu port 34, 74 entries per port */
            base = (mmu_port - 34) * 74;
        }

        for (idx = 0; idx < si->port_num_ext_cosq[port]; idx++) {
            /* coverity[overrun-local : FALSE] */
            buf_queue = &buf->ports[port].queues
                [si->port_num_cosq[port] + si->port_num_uc_cosq[port] + idx];

            sal_memset(entry0, 0, sizeof(mmu_thdo_config_ex_0_entry_t));
            sal_memset(entry1, 0, sizeof(mmu_thdo_offset_ex_0_entry_t));

            soc_mem_field32_set(unit, config_mem, entry0, Q_MIN_CELLf,
                                buf_queue->guarantee);
            if (buf_queue->discard_enable) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_LIMIT_ENABLE_CELLf, 1);
            }
            if (buf_queue->pool_scale != -1) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_LIMIT_DYNAMIC_CELLf, 1);
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_SHARED_ALPHA_CELLf,
                                    buf_queue->pool_scale);
            } else {
                /* Q_LIMIT_DYNAMIC_CELLf is 0 */
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_SHARED_LIMIT_CELLf,
                                    buf_queue->pool_limit);
            }
            soc_mem_field32_set(unit, offset_mem, entry1, RESET_OFFSET_CELLf,
                                buf_queue->pool_resume / 8);
            if (buf_queue->color_discard_enable) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_COLOR_ENABLE_CELLf, fval);
            }
            if (buf_queue->yellow_limit & _TD_BUF_DYNAMIC_FLAG) {
                soc_mem_field32_set(unit, config_mem, entry0,
                                    Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
                soc_mem_field32_set
                    (unit, config_mem, entry0, LIMIT_YELLOW_CELLf,
                     buf_queue->yellow_limit & ~_TD_BUF_DYNAMIC_FLAG);
                soc_mem_field32_set
                    (unit, offset_mem, entry1, LIMIT_RED_CELLf,
                     buf_queue->red_limit & ~_TD_BUF_DYNAMIC_FLAG);
            } else {
                /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
                soc_mem_field32_set
                    (unit, config_mem, entry0, LIMIT_YELLOW_CELLf,
                     buf_queue->yellow_limit / 8);
                soc_mem_field32_set
                    (unit, offset_mem, entry1, LIMIT_RED_CELLf,
                     buf_queue->red_limit / 8);
            }
            soc_mem_field32_set
                (unit, offset_mem, entry1, RESET_OFFSET_YELLOW_CELLf,
                 buf_queue->yellow_resume / 8);
            soc_mem_field32_set
                (unit, offset_mem, entry1, RESET_OFFSET_RED_CELLf,
                 buf_queue->red_resume / 8);
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL,
                               base + idx, entry0));
            SOC_IF_ERROR_RETURN
                (soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL,
                               base + idx, entry1));
        }
    }

    /* Output port per port settings */
    PBMP_PORT_ITER(unit, port) {
        buf_port = &buf->ports[port];

        /* regular unicast queue to pool mapping */
        count = si->port_num_uc_cosq[port];
        if (count > 0) {
            buf_queue = &buf->ports[port].queues[si->port_num_cosq[port]];
            rval = 0;
            if (si->port_num_ext_cosq[port] == 0) {
                for (idx = 0; idx < count; idx++) {
                    soc_reg_field_set(unit, OP_UC_PORT_CONFIG1_CELLr, &rval,
                                      uc_spid_field[idx],
                                      buf_queue[idx].pool_idx);
                }
                SOC_IF_ERROR_RETURN
                    (WRITE_OP_UC_PORT_CONFIG1_CELLr(unit, port, rval));
            } else {
                for (idx = 0; idx < count; idx++) {
                    soc_reg_field_set(unit, OP_EX_PORT_CONFIG_SPID_4r, &rval,
                                      ext_spid_field[idx + 64],
                                      buf_queue[idx].pool_idx);
                }
                SOC_IF_ERROR_RETURN
                    (WRITE_OP_EX_PORT_CONFIG_SPID_4r(unit, port, rval));
            }
        }

        /* extended unicast queue to pool mapping */
        count = SOC_PBMP_MEMBER(si->eq_pbm, port) ?
            si->port_num_ext_cosq[port] : 0;
        if (count > 0) {
            buf_queue = &buf_port->queues[si->port_num_cosq[port] +
                                          si->port_num_uc_cosq[port]];
            for (idx = 0; idx < count; idx++) {
                if (idx % 16 == 0) { /* 16 fields per register */
                    reg = ext_spid_reg[idx / 16];
                    rval = 0;
                }
                soc_reg_field_set(unit, reg, &rval, ext_spid_field[idx],
                                  buf_queue[idx].pool_idx);
                if (idx % 16 == 15) { /* 16 fields per register */
                    SOC_IF_ERROR_RETURN
                        (soc_reg32_set(unit, reg, port, 0, rval));
                }
            }
        }
    }

    /* Output port per pool settings */
    for (idx = 0; idx < _TD_MMU_NUM_POOL; idx++) {
        buf_pool = &buf->pools[idx];
        if ((buf_pool->size & ~_TD_BUF_PERCENT_FLAG) == 0) {
            continue;
        }
        limit = buf_pool->total + buf->port_guarantee -
            buf_pool->queue_guarantee;

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_SHARED_LIMIT_CELLr, &rval,
                          OP_BUFFER_SHARED_LIMIT_CELLf, limit);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_SHARED_LIMIT_CELLr, REG_PORT_ANY,
                           idx, rval));

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_LIMIT_YELLOW_CELLr, &rval,
                          OP_BUFFER_LIMIT_YELLOW_CELLf, limit / 8);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_LIMIT_YELLOW_CELLr, REG_PORT_ANY,
                           idx, rval));

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_LIMIT_RED_CELLr, &rval,
                          OP_BUFFER_LIMIT_RED_CELLf, limit / 8);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_LIMIT_RED_CELLr, REG_PORT_ANY,
                           idx, rval));

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_SHARED_LIMIT_RESUME_CELLr, &rval,
                          OP_BUFFER_SHARED_LIMIT_RESUME_CELLf, limit);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_SHARED_LIMIT_RESUME_CELLr,
                           REG_PORT_ANY, idx, rval));

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr, &rval,
                          OP_BUFFER_LIMIT_RESUME_YELLOW_CELLf, limit / 8);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr,
                           REG_PORT_ANY, idx, rval));

        rval = 0;
        soc_reg_field_set(unit, OP_BUFFER_LIMIT_RESUME_RED_CELLr, &rval,
                          OP_BUFFER_LIMIT_RESUME_RED_CELLf, limit / 8);
        SOC_IF_ERROR_RETURN
            (soc_reg32_set(unit, OP_BUFFER_LIMIT_RESUME_RED_CELLr,
                           REG_PORT_ANY, idx, rval));

        /* Output port per port per pool setting for unicast queues */
        PBMP_PORT_ITER(unit, port) {
            rval = 0;
            soc_reg_field_set(unit, OP_UC_PORT_CONFIG_CELLr, &rval,
                              OP_SHARED_LIMIT_CELLf, limit);
            soc_reg_field_set(unit, OP_UC_PORT_CONFIG_CELLr, &rval,
                              OP_SHARED_RESET_VALUE_CELLf,
                              limit - default_mtu_cells);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_UC_PORT_CONFIG_CELLr(unit, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, OP_UC_PORT_LIMIT_COLOR_CELLr, &rval, YELf,
                              limit / 8);
            soc_reg_field_set(unit, OP_UC_PORT_LIMIT_COLOR_CELLr, &rval, REDf,
                              limit / 8);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_UC_PORT_LIMIT_COLOR_CELLr(unit, port, idx, rval));

            rval = 0;
            soc_reg_field_set
                (unit, OP_UC_PORT_LIMIT_RESUME_COLOR_CELLr, &rval, YELf,
                 (limit - default_mtu_cells) / 8);
            soc_reg_field_set
                (unit, OP_UC_PORT_LIMIT_RESUME_COLOR_CELLr, &rval, REDf,
                 (limit - default_mtu_cells) / 8);
            SOC_IF_ERROR_RETURN
                (WRITE_OP_UC_PORT_LIMIT_RESUME_COLOR_CELLr
                 (unit, port, idx, rval));

            rval = 0;
        }

        /* Output port per port per pool setting for multicast queues */
        PBMP_ALL_ITER(unit, port) {
            rval = 0;
            soc_reg_field_set(unit, OP_PORT_CONFIG_CELLr, &rval,
                              OP_SHARED_LIMIT_CELLf, limit);
            soc_reg_field_set(unit, OP_UC_PORT_CONFIG_CELLr, &rval,
                              OP_SHARED_RESET_VALUE_CELLf,
                              limit - default_mtu_cells);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, OP_PORT_CONFIG_CELLr, port, idx, rval));

            rval = 0;
            soc_reg_field_set(unit, OP_PORT_LIMIT_COLOR_CELLr, &rval, REDf,
                              limit / 8);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, OP_PORT_LIMIT_COLOR_CELLr, port, idx,
                               rval));

            rval = 0;
            soc_reg_field_set
                (unit, OP_PORT_LIMIT_RESUME_COLOR_CELLr, &rval, REDf,
                              (limit - default_mtu_cells) / 8);
            SOC_IF_ERROR_RETURN
                (soc_reg32_set(unit, OP_PORT_LIMIT_RESUME_COLOR_CELLr, port,
                               idx, rval));
        }
    }

    return SOC_E_NONE;
}

int
soc_trident_mmu_config_init(int unit, int test_only)
{
    soc_info_t *si;
    _soc_trident_buf_t *buf;
    _soc_trident_buf_queue_t *buf_queue;
    int rv, port, alloc_size, num_cosq;

    si = &SOC_INFO(unit);

    alloc_size = sizeof(_soc_trident_buf_t);
    PBMP_ALL_ITER(unit, port) {
        num_cosq = si->port_num_cosq[port] + si->port_num_uc_cosq[port] +
            si->port_num_ext_cosq[port];
        alloc_size += sizeof(_soc_trident_buf_queue_t) * num_cosq;
    }
    buf = sal_alloc(alloc_size, "MMU config buffer");
    if (buf == NULL) {
        return SOC_E_MEMORY;
    }

    sal_memset(buf, 0, alloc_size);
    buf_queue = (_soc_trident_buf_queue_t *)&buf[1];
    PBMP_ALL_ITER(unit, port) {
        num_cosq = si->port_num_cosq[port] + si->port_num_uc_cosq[port] +
            si->port_num_ext_cosq[port];
        buf->ports[port].queues = buf_queue;
        buf_queue += num_cosq;
    }

    _soc_trident_mmu_config_buf_default(unit, buf);
    _soc_trident_mmu_config_buf_read(unit, buf);
    rv = _soc_trident_mmu_config_buf_check(unit, buf);
    if (!test_only) {
        if (SOC_FAILURE(rv)) {
            soc_cm_print("MMU config: Use default setting\n");
            _soc_trident_mmu_config_buf_default(unit, buf);
            _soc_trident_mmu_config_buf_calculate(unit, buf);
        }
        rv = _soc_trident_mmu_config_buf_set_hw(unit, buf);
    }

    sal_free(buf);

    return rv;
}

STATIC int
_soc_trident_mmu_init(int unit)
{
    soc_info_t *si;
    uint64 r64val0, r64val1, r64val2;
    uint32 rval0, rval1;
    uint32 rval_base[3][4], rval_credit[3];
    soc_pbmp_t pbmp0, pbmp1;
    int credit;
    int port, phy_port, mmu_port, idx, mode_idx, mode;
    int blk_bandwidth;
    uint32 mode4_bmp, mode2_bmp;
    static const soc_field_t gb_field[] = {
        GB_PORT0f, GB_PORT1f, GB_PORT2f, GB_PORT3f
    };

    si = &SOC_INFO(unit);

    /* Setup TDM for MMU */
    SOC_IF_ERROR_RETURN(_soc_trident_mmu_tdm_init(unit));

    /* Enable QGPORT (1G x 4) in XLPORT0 block (if present) */
    blk_bandwidth = 0;
    for (phy_port = 1; phy_port < 5; phy_port++) {
        port = si->port_p2l_mapping[phy_port];
        if (port != -1) {
            blk_bandwidth += si->port_speed_max[port];
        }
    }
    COMPILER_64_ZERO(r64val0);
    if (blk_bandwidth > 0 && blk_bandwidth <= 4000) {
        for (phy_port = 1; phy_port < 5; phy_port++) {
            mmu_port = si->port_p2m_mapping[phy_port];
            if (mmu_port < 0) {
                soc_reg64_field32_set(unit, ES_TDM_CONFIGr, &r64val0,
                                      gb_field[phy_port - 1], 0x3f);
            } else {
                soc_reg64_field32_set(unit, ES_TDM_CONFIGr, &r64val0,
                                      gb_field[phy_port - 1], mmu_port);
            }
        }
        soc_reg64_field32_set(unit, ES_TDM_CONFIGr, &r64val0,
                              EN_CPU_SLOT_SHARINGf, 1);
    }
    SOC_IF_ERROR_RETURN(WRITE_ES_TDM_CONFIGr(unit, r64val0));

    mode4_bmp = mode2_bmp = 0;
    for (mode_idx = 0; mode_idx < 16; mode_idx++) {
        /* 1, 2, 3, 4, 17, 18, 19, 20, 34, 35, 36, 37, 50, 51, 52, 53 */
        mmu_port = (((mode_idx & 0xc) << 2) | (mode_idx & 0x3)) +
            (mode_idx < 8 ? 1 : 2);
        if (si->port_m2p_mapping[mmu_port] == -1) {
            continue;
        }
        phy_port = si->port_m2p_mapping[mmu_port];
        port = si->port_p2l_mapping[phy_port];
        if (si->port_speed_max[port] > 20000) {
            if (si->port_m2p_mapping[mmu_port + 4] == -1 &&
                si->port_m2p_mapping[mmu_port + 8] == -1 &&
                si->port_m2p_mapping[mmu_port + 12] == -1) {
                mode4_bmp |= 1 << mode_idx;
            }
        } else if (si->port_speed_max[port] > 10000) {
            if (si->port_m2p_mapping[mmu_port + 4] == -1 &&
                si->port_m2p_mapping[mmu_port + 12] == -1) {
                mode2_bmp |= 1 << mode_idx;
            }
        }
    }
    rval0 = 0;
    soc_reg_field_set(unit, MCQ_CONFIGr, &rval0, MODE_4f, mode4_bmp);
    soc_reg_field_set(unit, MCQ_CONFIGr, &rval0, MODE_2f, mode2_bmp);
    SOC_IF_ERROR_RETURN(WRITE_MCQ_CONFIGr(unit, rval0));

    SOC_IF_ERROR_RETURN(soc_trident_mmu_config_init(unit, FALSE));

    rval0 = 0;
    soc_reg_field_set(unit, OP_THR_CONFIGr, &rval0, MOP_POLICYf, 7);
    soc_reg_field_set(unit, OP_THR_CONFIGr, &rval0, ASF_PKT_SIZEf, 3);
    soc_reg_field_set(unit, OP_THR_CONFIGr, &rval0, ASF_QUEUE_SIZEf, 3);
    soc_reg_field_set(unit, OP_THR_CONFIGr, &rval0, YELLOW_CELL_DS_SELECTf, 1);
    SOC_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval0));

    /* Set extended queue ports to use queue mode accounting */
    rval0 = 0;
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P1f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P2f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P3f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P4f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P34f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P35f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P36f, 1);
    soc_reg_field_set(unit, OP_VOQ_PORT_CONFIGr, &rval0, Q_SEL_P37f, 1);
    SOC_IF_ERROR_RETURN(WRITE_OP_VOQ_PORT_CONFIGr(unit, rval0));

    /* OVQ settings */
    rval0 = 0;
    soc_reg_field_set(unit, OVQ_DROP_THRESHOLD0r, &rval0,
                      OVQ_DROP_THRESHOLD0f, _TD_MMU_TOTAL_CELLS / 4);
    SOC_IF_ERROR_RETURN(WRITE_OVQ_DROP_THRESHOLD0r(unit, rval0));

    rval0 = 0;
    soc_reg_field_set(unit, OVQ_DROP_THRESHOLD_RESET_LIMITr, &rval0,
                      OVQ_DROP_THRESHOLD_RESET_LIMITf,
                      _TD_MMU_TOTAL_CELLS / 4);
    SOC_IF_ERROR_RETURN
        (WRITE_OVQ_DROP_THRESHOLD_RESET_LIMITr(unit, rval0));

    rval0 = 0;
    soc_reg_field_set(unit, OVQ_FLOWCONTROL_THRESHOLDr, &rval0, OVQ_FC_ENABLEf,
                      1);
    soc_reg_field_set(unit, OVQ_FLOWCONTROL_THRESHOLDr, &rval0,
                      OVQ_FC_THRESHOLDf, 11250);
    soc_reg_field_set(unit, OVQ_FLOWCONTROL_THRESHOLDr, &rval0,
                      OVQ_FC_THRESHOLD_RESET_LIMITf, 11249);
    SOC_IF_ERROR_RETURN(WRITE_OVQ_FLOWCONTROL_THRESHOLDr(unit, rval0));

    sal_memset(rval_base, 0, sizeof(rval_base));
    sal_memset(rval_credit, 0, sizeof(rval_credit));
    for (mode = 0; mode < 3; mode++) { /* MODE_1, MODE_2, MODE_4 */
        /* MODE_x means a port has x subports, each subport has 1000 credits,
         * divide total credit from all subports by 5 multicast queues,
         * then truncate the result to multiple of 16 */
        credit = ((1 << mode) * 1000 / 5) & ~0xf;
        soc_reg_field_set(unit, OVQ_MCQ_CREDITSr, &rval_credit[mode], CREDITSf,
                          credit);
        for (idx = 0; idx < 4; idx++) {
            soc_reg_field_set(unit, MCQ_FIFO_BASE_REGr, &rval_base[mode][idx],
                          Q_MCQ_FIFO_BASEf, credit / 16 * (idx + 1));
        }
    }
    PBMP_ALL_ITER(unit, port) {
        if (IS_CPU_PORT(unit, port)) {
            continue;
        }
        if (IS_LB_PORT(unit, port)) {
            mode = 0; /* MODE_1 */
        } else {
            phy_port = si->port_l2p_mapping[port];
            mmu_port = si->port_p2m_mapping[phy_port];
            /* 1, 2, 3, 4, 17, 18, 19, 20, 34, 35, 36, 37, 50, 51, 52, 53 */
            mode_idx = mmu_port - 1 - (mmu_port > 33 ? 1 : 0);
            mode_idx = ((mode_idx & 0x30) >> 2) + (mode_idx & 3);
            if (mode4_bmp & (1 << mode_idx)) {
                mode = 2; /* MODE_4 */
            } else if (mode2_bmp & (1 << mode_idx)) {
                mode = 1; /* MODE_2 */
            } else {
                mode = 0; /* MODE_1 */
            }
        }
        for (idx = 0; idx < 5; idx++) {
            SOC_IF_ERROR_RETURN
                (WRITE_OVQ_MCQ_CREDITSr(unit, port, idx, rval_credit[mode]));
            if (idx > 0) {
                SOC_IF_ERROR_RETURN
                    (WRITE_MCQ_FIFO_BASE_REGr(unit, port, idx,
                                              rval_base[mode][idx - 1]));
            }
        }
    }

    SOC_PBMP_CLEAR(pbmp0);
    SOC_PBMP_CLEAR(pbmp1);
    PBMP_ALL_ITER(unit, port) {
        mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[port]];
        if (IS_CPU_PORT(unit, port) ||
            (si->port_group[port] >= 0 && si->port_group[port] <= 1)) {
            SOC_PBMP_PORT_ADD(pbmp0, mmu_port);
        } else {
            SOC_PBMP_PORT_ADD(pbmp1, mmu_port - 33);
        }
    }

    /* Enable pause */
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, PORT_PAUSE_ENABLE0_64r, &r64val0,
                          PORT_PAUSE_ENABLE_LOf,
                          SOC_PBMP_WORD_GET(pbmp0, 0));
    soc_reg64_field32_set(unit, PORT_PAUSE_ENABLE0_64r, &r64val0,
                          PORT_PAUSE_ENABLE_HIf,
                          SOC_PBMP_WORD_GET(pbmp0, 1));
    SOC_IF_ERROR_RETURN(WRITE_PORT_PAUSE_ENABLE0_64r(unit, r64val0));
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, PORT_PAUSE_ENABLE1_64r, &r64val0,
                          PORT_PAUSE_ENABLE_LOf,
                          SOC_PBMP_WORD_GET(pbmp1, 0));
    soc_reg64_field32_set(unit, PORT_PAUSE_ENABLE1_64r, &r64val0,
                          PORT_PAUSE_ENABLE_HIf,
                          SOC_PBMP_WORD_GET(pbmp1, 1));
    SOC_IF_ERROR_RETURN(WRITE_PORT_PAUSE_ENABLE1_64r(unit, r64val0));

    /* Enable input port */
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, INPUT_PORT_RX_ENABLE0_64r, &r64val0,
                          INPUT_PORT_RX_ENABLE_LOf,
                          SOC_PBMP_WORD_GET(pbmp0, 0));
    soc_reg64_field32_set(unit, INPUT_PORT_RX_ENABLE0_64r, &r64val0,
                          INPUT_PORT_RX_ENABLE_HIf,
                          SOC_PBMP_WORD_GET(pbmp0, 1));
    SOC_IF_ERROR_RETURN(WRITE_INPUT_PORT_RX_ENABLE0_64r(unit, r64val0));
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, INPUT_PORT_RX_ENABLE1_64r, &r64val0,
                          INPUT_PORT_RX_ENABLE_LOf,
                          SOC_PBMP_WORD_GET(pbmp1, 0));
    soc_reg64_field32_set(unit, INPUT_PORT_RX_ENABLE1_64r, &r64val0,
                          INPUT_PORT_RX_ENABLE_HIf,
                          SOC_PBMP_WORD_GET(pbmp1, 1));
    SOC_IF_ERROR_RETURN(WRITE_INPUT_PORT_RX_ENABLE1_64r(unit, r64val0));

    /* Enable output port */
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, OUTPUT_PORT_RX_ENABLE0_64r, &r64val0,
                          OUTPUT_PORT_RX_ENABLE0_LOf,
                          SOC_PBMP_WORD_GET(pbmp0, 0));
    soc_reg64_field32_set(unit, OUTPUT_PORT_RX_ENABLE0_64r, &r64val0,
                          OUTPUT_PORT_RX_ENABLE0_HIf,
                          SOC_PBMP_WORD_GET(pbmp0, 1));
    SOC_IF_ERROR_RETURN(WRITE_OUTPUT_PORT_RX_ENABLE0_64r(unit, r64val0));
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, OUTPUT_PORT_RX_ENABLE1_64r, &r64val0,
                          OUTPUT_PORT_RX_ENABLE1_LOf,
                          SOC_PBMP_WORD_GET(pbmp1, 0));
    soc_reg64_field32_set(unit, OUTPUT_PORT_RX_ENABLE1_64r, &r64val0,
                          OUTPUT_PORT_RX_ENABLE1_HIf,
                          SOC_PBMP_WORD_GET(pbmp1, 1));
    SOC_IF_ERROR_RETURN(WRITE_OUTPUT_PORT_RX_ENABLE1_64r(unit, r64val0));

    /*
     * default scheduling:
     *     unicast queue 0 and multicast queue 0 connect to S3.0
     *     unicast queue 1 and multicast queue 1 connect to S3.1
     *     unicast queue 2 and multicast queue 2 connect to S3.2
     *     unicast queue 3 and multicast queue 3 connect to S3.3
     *     S3.0 - S3.3 and unicast queue 4 - 7 connect to S2.0
     *     S2.1, S2.2, MC group are not used
     */
    rval0 = 0;
    soc_reg_field_set(unit, S3_CONFIGr, &rval0, SCHEDULING_SELECTf, 0x55);

    rval1 = 0;
    soc_reg_field_set(unit, S2_CONFIGr, &rval1, SCHEDULING_SELECTf, 0x15);

    /* S3.0 - S3.3 and unicast queues 4 - 7 to S2.0 */
    COMPILER_64_ZERO(r64val0);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I0f, 0);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I1f, 1);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I2f, 2);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I3f, 3);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I4f, 8);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I5f, 9);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I6f, 10);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I7f, 11);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val0, S3_GROUP_NO_I8f,
                          0x1f);

    COMPILER_64_ZERO(r64val1);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I0f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I1f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I2f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I3f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I4f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I5f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I6f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I7f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I7f,
                          0x1f);
    soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &r64val1, S3_GROUP_NO_I8f,
                          0x1f);
    /* S2.1 and S2.2 are not used */
    r64val2 = r64val1;

    PBMP_PORT_ITER(unit, port) {
        SOC_IF_ERROR_RETURN(WRITE_S3_CONFIGr(unit, port, rval0));
        SOC_IF_ERROR_RETURN(WRITE_S2_CONFIGr(unit, port, rval1));
        SOC_IF_ERROR_RETURN(WRITE_S2_S3_ROUTINGr(unit, port, 0, r64val0));
        SOC_IF_ERROR_RETURN(WRITE_S2_S3_ROUTINGr(unit, port, 1, r64val1));
        SOC_IF_ERROR_RETURN(WRITE_S2_S3_ROUTINGr(unit, port, 2, r64val2));
    }

    return SOC_E_NONE;
}

STATIC int
_soc_trident_age_timer_get(int unit, int *age_seconds, int *enabled)
{
    uint32 rval;

    SOC_IF_ERROR_RETURN(READ_L2_AGE_TIMERr(unit, &rval));
    *enabled = soc_reg_field_get(unit, L2_AGE_TIMERr, rval, AGE_ENAf);
    *age_seconds = soc_reg_field_get(unit, L2_AGE_TIMERr, rval, AGE_VALf);

    return SOC_E_NONE;
}

STATIC int
_soc_trident_age_timer_max_get(int unit, int *max_seconds)
{
    *max_seconds =
        soc_reg_field_get(unit, L2_AGE_TIMERr, 0xffffffff, AGE_VALf);

    return SOC_E_NONE;
}

STATIC int
_soc_trident_age_timer_set(int unit, int age_seconds, int enable)
{
    uint32 rval;

    rval = 0;
    soc_reg_field_set(unit, L2_AGE_TIMERr, &rval, AGE_ENAf, enable);
    soc_reg_field_set(unit, L2_AGE_TIMERr, &rval, AGE_VALf, age_seconds);
    SOC_IF_ERROR_RETURN(WRITE_L2_AGE_TIMERr(unit, rval));

    return SOC_E_NONE;
}

/*
 * Trident chip driver functions.
 */
soc_functions_t soc_trident_drv_funs = {
    _soc_trident_misc_init,
    _soc_trident_mmu_init,
    _soc_trident_age_timer_get,
    _soc_trident_age_timer_max_get,
    _soc_trident_age_timer_set,
};

static const soc_reg_t thermal_reg[] = {
    CMIC_THERMAL_MON_RESULT_0r, CMIC_THERMAL_MON_RESULT_1r,
    CMIC_THERMAL_MON_RESULT_2r, CMIC_THERMAL_MON_RESULT_3r,
    CMIC_THERMAL_MON_RESULT_4r, CMIC_THERMAL_MON_RESULT_5r,
    CMIC_THERMAL_MON_RESULT_6r, CMIC_THERMAL_MON_RESULT_7r
};

int
soc_trident_show_temperature_monitor(int unit)
{
    uint32 rval, addr;
    soc_reg_t reg;
    int index;
    int fval, cur, peak, avg_cur, max_peak;
    uint16 dev_id, drv_dev_id;
    uint8 rev_id, drv_rev_id;

    soc_cm_get_id(unit, &dev_id, &rev_id);
    soc_cm_get_id_driver(dev_id, rev_id, &drv_dev_id, &drv_rev_id);

    if (!(drv_rev_id == BCM56840_A0_REV_ID && rev_id < BCM56840_B0_REV_ID)) {
        reg = CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r;
        READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
        soc_reg_field_set(unit, reg, &rval, PVTMON_SELECTf, 0);
        soc_reg_field_set(unit, reg, &rval, BG_ADJf, 3);
        soc_reg_field_set(unit, reg, &rval, VTMON_7_OR_PVTMON_SELf, 1);
        soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 0);
        WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);
        soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 1);
        WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);
    }

    sal_usleep(1000);

    READ_CMIC_THERMAL_MON_CTRLr(unit, &rval);
    soc_reg_field_set(unit, CMIC_THERMAL_MON_CTRLr, &rval, BG_ADJf, 1);
    soc_reg_field_set(unit, CMIC_THERMAL_MON_CTRLr, &rval, VTMON_RSTBf, 1);
    WRITE_CMIC_THERMAL_MON_CTRLr(unit, rval);

    sal_usleep(1000);

    avg_cur = 0;
    max_peak = 0x80000000;
    for (index = 0; index < 8; index++) {
        reg = thermal_reg[index];
        addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
        soc_pci_getreg(unit, addr, &rval);
        fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
        cur = (4100000 - (5424 * fval)) / 10000;
        fval = soc_reg_field_get(unit, reg, rval, PEAK_TEMP_DATAf);
        peak = (4100000 - (5424 * fval)) / 10000;
        soc_cm_print("temperature monitor %d: current=%3d, peak=%3d\n",
                     index, cur, peak);
        avg_cur += cur;
        if (max_peak < peak) {
            max_peak = peak;
        }
    }
    soc_cm_print("average current temperature is %d\n", avg_cur / 8);
    soc_cm_print("maximum peak temperature is %d\n", max_peak);

    READ_CMIC_SOFT_RESET_REGr(unit, &rval);
    soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval,
                      CMIC_TEMP_MON_PEAK_RST_Lf, 0);
    WRITE_CMIC_SOFT_RESET_REGr(unit, rval);
    soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval,
                      CMIC_TEMP_MON_PEAK_RST_Lf, 1);
    WRITE_CMIC_SOFT_RESET_REGr(unit, rval);

    return SOC_E_NONE;
}

int
soc_trident_show_material_process(int unit)
{
    soc_reg_t reg;
    uint32 addr, rval, fval, nmos_4, nmos_7_0, nmos_7_1, n_avg, p_avg;
    uint16 dev_id, drv_dev_id;
    uint8 rev_id, drv_rev_id;

    soc_cm_get_id(unit, &dev_id, &rev_id);
    soc_cm_get_id_driver(dev_id, rev_id, &drv_dev_id, &drv_rev_id);

    if (drv_rev_id == BCM56840_A0_REV_ID && rev_id < BCM56840_B0_REV_ID) {
        return SOC_E_UNAVAIL;
    }

    n_avg = 0;
    p_avg = 0;

    /* Read NMOS information */
    reg = CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r;
    READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
    soc_reg_field_set(unit, reg, &rval, PVTMON_SELECTf, 1);
    soc_reg_field_set(unit, reg, &rval, PROG_RESISTORf, 3);
    soc_reg_field_set(unit, reg, &rval, MEASUREMENT_CALLIBRATIONf, 5);
    soc_reg_field_set(unit, reg, &rval, BG_ADJf, 3);
    soc_reg_field_set(unit, reg, &rval, VTMON_7_OR_PVTMON_SELf, 1);
    soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 0);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);
    soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 1);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);

    sal_usleep(1000);

    reg = thermal_reg[4];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    nmos_4 = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    n_avg += nmos_4;

    reg = thermal_reg[7];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    nmos_7_1 = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    n_avg += nmos_7_1;

    READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
    soc_reg_field_set(unit, CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r,
                      &rval, VTMON_7_OR_PVTMON_SELf, 0);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);

    reg = thermal_reg[7];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    nmos_7_0 = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    n_avg += nmos_7_0;

    /* Read PMOS information */
    reg = CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r;
    READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
    soc_reg_field_set(unit, reg, &rval, MEASUREMENT_CALLIBRATIONf, 7);
    soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 0);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);
    soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 1);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);

    sal_usleep(1000);

    reg = thermal_reg[4];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    soc_cm_print("material process location 4  : NMOS = %3d PMOS = %3d\n",
                 nmos_4, fval);
    p_avg += fval;

    reg = thermal_reg[7];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    soc_cm_print("material process location 7-1: NMOS = %3d PMOS = %3d\n",
                 nmos_7_1, fval);
    p_avg += fval;

    READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
    soc_reg_field_set(unit, CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r, &rval,
                      VTMON_7_OR_PVTMON_SELf, 0);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);

    reg = thermal_reg[7];
    addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
    soc_pci_getreg(unit, addr, &rval);
    fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf);
    soc_cm_print("material process location 7-0: NMOS = %3d PMOS = %3d\n",
                 nmos_7_0, fval);
    soc_cm_print("average:                       NMOS = %3d PMOS = %3d\n",
                 n_avg / 3, p_avg / 3);

    reg = CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r;
    READ_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, &rval);
    soc_reg_field_set(unit, reg, &rval, PVTMON_SELECTf, 0);
    soc_reg_field_set(unit, reg, &rval, BG_ADJf, 3);
    soc_reg_field_set(unit, reg, &rval, VTMON_7_OR_PVTMON_SELf, 1);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);
    soc_reg_field_set(unit, reg, &rval, PVTMON_RESET_Nf, 1);
    WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_3r(unit, rval);

    sal_usleep(1000);

    READ_CMIC_SOFT_RESET_REGr(unit, &rval);
    soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval,
                      CMIC_TEMP_MON_PEAK_RST_Lf, 0);
    WRITE_CMIC_SOFT_RESET_REGr(unit, rval);
    soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval,
                      CMIC_TEMP_MON_PEAK_RST_Lf, 1);
    WRITE_CMIC_SOFT_RESET_REGr(unit, rval);

    return SOC_E_NONE;
}

int
soc_trident_show_ring_osc(int unit)
{
    soc_info_t *si;
    soc_reg_t reg;
    static const soc_field_t fields[] = {
        OSC_0_SELf, OSC_1_SELf, IROSC_SELf, IROSC_SELf
    };
    static const int counts[] = { 4, 4, 2, 2 };
    static char *names[] = {
        "IO ring 0", "IO ring 1", "Core ring 0", "Core ring 1"
    };
    uint32 rval;
    int ring, set, core_clk, div, quo, rem, frac;

    si = &SOC_INFO(unit);
    core_clk = (si->bandwidth == 640000 ? 495 : 415) * 1024;

    reg = CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_2r;
    if (!soc_reg_field_valid(unit, reg, OSC_ENABLEf)) {
        return SOC_E_UNAVAIL;
    }

    /*
     * IO ring osc 0 has 4 sets of value
     * IO ring osc 1 has 4 sets of value
     * Core ring osc 0 has 2 sets of value
     * Core ring osc 1 has 2 sets of value
     */
    for (ring = 0; ring < 4; ring++) {
        for (set = 0; set < counts[ring]; set++) {
            rval = 0;
            SOC_IF_ERROR_RETURN
                (WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_2r(unit, rval));
            soc_reg_field_set(unit, reg, &rval, OSC_ENABLEf, 1);
            soc_reg_field_set(unit, reg, &rval, IROSC_ENf, 1);
            soc_reg_field_set(unit, reg, &rval, fields[ring], set);
            soc_reg_field_set(unit, reg, &rval, OSC_SELf, ring);
            SOC_IF_ERROR_RETURN
                (WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_2r(unit, rval));
            soc_reg_field_set(unit, reg, &rval, OSC_CNT_RSTBf, 1);
            SOC_IF_ERROR_RETURN
                (WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_2r(unit, rval));
            soc_reg_field_set(unit, reg, &rval, OSC_CNT_STARTf, 1);
            SOC_IF_ERROR_RETURN
                (WRITE_CMIC_CORE_PLL3_CTRL_STATUS_REGISTER_2r(unit, rval));

            sal_usleep(1000);

            /*
             * ring_osc_freq = core_clock_freq * 1024 / div
             * core ring 0 set 1 or core ring 1 set 1:
             *    div = CMIC_IRQ_STAT_1[15:0] + 65536
             * otherwise
             *    div = CMIC_IRQ_STAT_1[15:0]
             */
            SOC_IF_ERROR_RETURN(READ_CMIC_IRQ_STAT_1r(unit, &rval));
            div = rval & 0xffff;
            if (ring >= 2 && set == 1) { /* core ring 0/1 set 1 */
                div += 65536;
            }
            quo = core_clk / div;
            rem = core_clk - quo * div;
            frac = (rem * 10000) / div;
            soc_cm_print("%s set %d: %d.%04d Mhz\n",
                         names[ring], set, quo, frac);
        }
    }

    return SOC_E_NONE;
}

#endif /* BCM_TRIDENT_SUPPORT */
